From 8616e0fc1e27295316f9821a883f0e9fa6f8200f Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 11 Jun 2009 10:27:28 -0400 Subject: [PATCH 0001/1002] cifs: remove unneeded NULL checks from cifs_show_options show_options is always called with the namespace_sem held. Therefore we don't need to worry about the vfsmount being NULL, or it vanishing while the function is running. By the same token, there's no need to worry about the superblock, tcon, smb or tcp sessions being NULL on entry. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 130 +++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 71 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0d92114195ab6..3f121fbd6c566 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -346,80 +346,68 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) struct TCP_Server_Info *server; cifs_sb = CIFS_SB(m->mnt_sb); + tcon = cifs_sb->tcon; - if (cifs_sb) { - tcon = cifs_sb->tcon; - if (tcon) { - seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); - if (tcon->ses) { - if (tcon->ses->userName) - seq_printf(s, ",username=%s", - tcon->ses->userName); - if (tcon->ses->domainName) - seq_printf(s, ",domain=%s", - tcon->ses->domainName); - server = tcon->ses->server; - if (server) { - seq_printf(s, ",addr="); - switch (server->addr.sockAddr6. - sin6_family) { - case AF_INET6: - seq_printf(s, "%pI6", - &server->addr.sockAddr6.sin6_addr); - break; - case AF_INET: - seq_printf(s, "%pI4", - &server->addr.sockAddr.sin_addr.s_addr); - break; - } - } - } - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || - !(tcon->unix_ext)) - seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || - !(tcon->unix_ext)) - seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); - if (!tcon->unix_ext) { - seq_printf(s, ",file_mode=0%o,dir_mode=0%o", + seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); + if (tcon->ses->userName) + seq_printf(s, ",username=%s", tcon->ses->userName); + if (tcon->ses->domainName) + seq_printf(s, ",domain=%s", tcon->ses->domainName); + + cifs_show_address(s, tcon->ses->server); + + seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); + seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); + + server = tcon->ses->server; + seq_printf(s, ",addr="); + switch (server->addr.sockAddr6.sin6_family) { + case AF_INET6: + seq_printf(s, "%pI6", &server->addr.sockAddr6.sin6_addr); + break; + case AF_INET: + seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); + break; + } + + if (!tcon->unix_ext) + seq_printf(s, ",file_mode=0%o,dir_mode=0%o", cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); - } - if (tcon->seal) - seq_printf(s, ",seal"); - if (tcon->nocase) - seq_printf(s, ",nocase"); - if (tcon->retry) - seq_printf(s, ",hard"); - } - if (cifs_sb->prepath) - seq_printf(s, ",prepath=%s", cifs_sb->prepath); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) - seq_printf(s, ",posixpaths"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) - seq_printf(s, ",setuids"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) - seq_printf(s, ",serverino"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) - seq_printf(s, ",directio"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - seq_printf(s, ",nouser_xattr"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) - seq_printf(s, ",mapchars"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) - seq_printf(s, ",sfu"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - seq_printf(s, ",nobrl"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) - seq_printf(s, ",cifsacl"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) - seq_printf(s, ",dynperm"); - if (m->mnt_sb->s_flags & MS_POSIXACL) - seq_printf(s, ",acl"); - - seq_printf(s, ",rsize=%d", cifs_sb->rsize); - seq_printf(s, ",wsize=%d", cifs_sb->wsize); - } + if (tcon->seal) + seq_printf(s, ",seal"); + if (tcon->nocase) + seq_printf(s, ",nocase"); + if (tcon->retry) + seq_printf(s, ",hard"); + if (cifs_sb->prepath) + seq_printf(s, ",prepath=%s", cifs_sb->prepath); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) + seq_printf(s, ",posixpaths"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) + seq_printf(s, ",setuids"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + seq_printf(s, ",serverino"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + seq_printf(s, ",directio"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + seq_printf(s, ",nouser_xattr"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) + seq_printf(s, ",mapchars"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) + seq_printf(s, ",sfu"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) + seq_printf(s, ",nobrl"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) + seq_printf(s, ",cifsacl"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) + seq_printf(s, ",dynperm"); + if (m->mnt_sb->s_flags & MS_POSIXACL) + seq_printf(s, ",acl"); + + seq_printf(s, ",rsize=%d", cifs_sb->rsize); + seq_printf(s, ",wsize=%d", cifs_sb->wsize); + return 0; } -- GitLab From 340481a36498bf3fe404bcecb2e2d6188e950bff Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 11 Jun 2009 10:27:29 -0400 Subject: [PATCH 0002/1002] cifs: have cifs_show_options show forceuid/forcegid options Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3f121fbd6c566..8b315708cb3fb 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -357,7 +357,12 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) cifs_show_address(s, tcon->ses->server); seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) + seq_printf(s, ",forceuid"); + seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) + seq_printf(s, ",forcegid"); server = tcon->ses->server; seq_printf(s, ",addr="); -- GitLab From 1e68b2b2756fc3488ecbade5ad5f13302b3aaafc Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 11 Jun 2009 10:27:30 -0400 Subject: [PATCH 0003/1002] cifs: add new routine for converting AF_INET and AF_INET6 addrs ...to consolidate some logic used in more than one place. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsproto.h | 2 +- fs/cifs/connect.c | 21 ++++----------------- fs/cifs/dns_resolve.c | 21 +++------------------ fs/cifs/netmisc.c | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f9452329bcce5..c419416a42eef 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -74,7 +74,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, enum securityEnum *secType); -extern int cifs_inet_pton(const int, const char *source, void *dst); +extern int cifs_convert_address(char *src, void *dst); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 97f4311b9a8ea..c368ad6582367 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1433,28 +1433,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info) memset(&addr, 0, sizeof(struct sockaddr_storage)); - if (volume_info->UNCip && volume_info->UNC) { - rc = cifs_inet_pton(AF_INET, volume_info->UNCip, - &sin_server->sin_addr.s_addr); - - if (rc <= 0) { - /* not ipv4 address, try ipv6 */ - rc = cifs_inet_pton(AF_INET6, volume_info->UNCip, - &sin_server6->sin6_addr.in6_u); - if (rc > 0) - addr.ss_family = AF_INET6; - } else { - addr.ss_family = AF_INET; - } + cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip)); - if (rc <= 0) { + if (volume_info->UNCip && volume_info->UNC) { + rc = cifs_convert_address(volume_info->UNCip, &addr); + if (!rc) { /* we failed translating address */ rc = -EINVAL; goto out_err; } - - cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, - volume_info->UNCip)); } else if (volume_info->UNCip) { /* BB using ip addr as tcp_ses name to connect to the DFS root below */ diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index df4a306f697ef..91b5500755bf8 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -37,24 +37,9 @@ static int is_ip(const char *name) { - int rc; - struct sockaddr_in sin_server; - struct sockaddr_in6 sin_server6; - - rc = cifs_inet_pton(AF_INET, name, - &sin_server.sin_addr.s_addr); - - if (rc <= 0) { - /* not ipv4 address, try ipv6 */ - rc = cifs_inet_pton(AF_INET6, name, - &sin_server6.sin6_addr.in6_u); - if (rc > 0) - return 1; - } else { - return 1; - } - /* we failed translating address */ - return 0; + struct sockaddr_storage ss; + + return cifs_convert_address(name, &ss); } static int diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 32d6baa0a54fa..00e6e357ae885 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { {0, 0} }; -/* Convert string containing dotted ip address to binary form */ -/* returns 0 if invalid address */ - -int +/* + * Convert a string containing text IPv4 or IPv6 address to binary form. + * + * Returns 0 on failure. + */ +static int cifs_inet_pton(const int address_family, const char *cp, void *dst) { int ret = 0; @@ -153,6 +155,30 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) return ret; } +/* + * Try to convert a string to an IPv4 address and then attempt to convert + * it to an IPv6 address if that fails. Set the family field if either + * succeeds. + * + * Returns 0 on failure. + */ +int +cifs_convert_address(char *src, void *dst) +{ + struct sockaddr_in *s4 = (struct sockaddr_in *) dst; + struct sockaddr_in6 *s6 = (Struct sockaddr_in6 *) dst; + + if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { + s4->sin_family = AF_INET; + return 1; + } else if (cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr)) { + s6->sin6_family = AF_INET6; + return 1; + } + + return 0; +} + /***************************************************************************** convert a NT status code to a dos class/code *****************************************************************************/ -- GitLab From 3a45c9e4b192c9e96f65a8473c7a28e09cf2ac2a Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Sat, 13 Jun 2009 10:43:19 +0100 Subject: [PATCH 0004/1002] MAINTAINERS: Update file list for ARM/S3C2410 and ARM/S3C2440 Add F: entries for ARM/S3C2410 and ARM/S3C2440 to update the entries. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 90f81283b722d..fa9377df160d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -830,6 +830,7 @@ M: ben-linux@fluff.org L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained +F: arch/arm/mach-s3c2410/ ARM/S3C2440 ARM ARCHITECTURE P: Ben Dooks @@ -837,6 +838,7 @@ M: ben-linux@fluff.org L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.fluff.org/ben/linux/ S: Maintained +F: arch/arm/mach-s3c2440/ ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT P: Lennert Buytenhek -- GitLab From b21477f9d257cd8d45f7df32a9ebed45dbdfa4b5 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Sat, 13 Jun 2009 10:46:34 +0100 Subject: [PATCH 0005/1002] MAINTAINERS: Add ARM S3C2442, S3C2443, S3C6400, S3C6410 and ARM/SAMSUNG Add entries for the ARM architectures and platform support that are currently being maintained by myself. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- MAINTAINERS | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fa9377df160d3..293cba0dc121b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -824,6 +824,15 @@ M: alex@shark-linux.de W: http://www.shark-linux.de/shark.html S: Maintained +ARM/SAMSUNG ARM ARCHITECTURES +P: Ben Dooks +M: ben-linux@fluff.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.fluff.org/ben/linux/ +S: Maintained +F: arch/arm/plat-s3c/ +F: arch/arm/plat-s3c24xx/ + ARM/S3C2410 ARM ARCHITECTURE P: Ben Dooks M: ben-linux@fluff.org @@ -840,6 +849,38 @@ W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2440/ +ARM/S3C2442 ARM ARCHITECTURE +P: Ben Dooks +M: ben-linux@fluff.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.fluff.org/ben/linux/ +S: Maintained +F: arch/arm/mach-s3c2442/ + +ARM/S3C2443 ARM ARCHITECTURE +P: Ben Dooks +M: ben-linux@fluff.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.fluff.org/ben/linux/ +S: Maintained +F: arch/arm/mach-s3c2443/ + +ARM/S3C6400 ARM ARCHITECTURE +P: Ben Dooks +M: ben-linux@fluff.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.fluff.org/ben/linux/ +S: Maintained +F: arch/arm/mach-s3c6400/ + +ARM/S3C6410 ARM ARCHITECTURE +P: Ben Dooks +M: ben-linux@fluff.org +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.fluff.org/ben/linux/ +S: Maintained +F: arch/arm/mach-s3c6410/ + ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT P: Lennert Buytenhek M: kernel@wantstofly.org -- GitLab From 61f98ffd74254a95871168bd5a6646b4f3002e31 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 11 Jun 2009 10:27:32 -0400 Subject: [PATCH 0006/1002] cifs: display scopeid in /proc/mounts Move address display into a new function and display the scopeid as part of the address in /proc/mounts. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8b315708cb3fb..ddef913ff3e67 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -333,6 +333,27 @@ cifs_destroy_inode(struct inode *inode) kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); } +static void +cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) +{ + seq_printf(s, ",addr="); + + switch (server->addr.sockAddr.sin_family) { + case AF_INET: + seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); + break; + case AF_INET6: + seq_printf(s, "%pI6", + &server->addr.sockAddr6.sin6_addr.s6_addr); + if (server->addr.sockAddr6.sin6_scope_id) + seq_printf(s, "%%%u", + server->addr.sockAddr6.sin6_scope_id); + break; + default: + seq_printf(s, "(unknown)"); + } +} + /* * cifs_show_options() is for displaying mount options in /proc/mounts. * Not all settable options are displayed but most of the important @@ -343,7 +364,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) { struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; - struct TCP_Server_Info *server; cifs_sb = CIFS_SB(m->mnt_sb); tcon = cifs_sb->tcon; @@ -364,16 +384,7 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) seq_printf(s, ",forcegid"); - server = tcon->ses->server; - seq_printf(s, ",addr="); - switch (server->addr.sockAddr6.sin6_family) { - case AF_INET6: - seq_printf(s, "%pI6", &server->addr.sockAddr6.sin6_addr); - break; - case AF_INET: - seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); - break; - } + cifs_show_address(s, tcon->ses->server); if (!tcon->unix_ext) seq_printf(s, ",file_mode=0%o,dir_mode=0%o", -- GitLab From 361ea1ae5451040cd254eee0b6df64581080b2cc Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Mon, 15 Jun 2009 13:46:12 +0000 Subject: [PATCH 0007/1002] [CIFS] Fix build break Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/netmisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 00e6e357ae885..f9a54da97d345 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -166,7 +166,7 @@ int cifs_convert_address(char *src, void *dst) { struct sockaddr_in *s4 = (struct sockaddr_in *) dst; - struct sockaddr_in6 *s6 = (Struct sockaddr_in6 *) dst; + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { s4->sin_family = AF_INET; -- GitLab From c79ee4e466dd12347f112e2af306dca35198458f Mon Sep 17 00:00:00 2001 From: Joerg Roedel <joerg.roedel@amd.com> Date: Tue, 16 Jun 2009 12:23:58 +0200 Subject: [PATCH 0008/1002] dma-debug: fix off-by-one error in overlap function This patch fixes a bug in the overlap function which returned true if one region ends exactly before the second region begins. This is no overlap but the function returned true in that case. Cc: stable@kernel.org Reported-by: Andrew Randrianasulu <randrik@mail.ru> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> --- lib/dma-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 3b93129a968c7..a9b6b5c9e0916 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -862,7 +862,7 @@ static inline bool overlap(void *addr, u64 size, void *start, void *end) return ((addr >= start && addr < end) || (addr2 >= start && addr2 < end) || - ((addr < start) && (addr2 >= end))); + ((addr < start) && (addr2 > end))); } static void check_for_illegal_area(struct device *dev, void *addr, u64 size) -- GitLab From b0a5b83ee0fce9dbf8ff5fe1f8c9ae7dfafe458c Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Tue, 16 Jun 2009 16:11:14 +0200 Subject: [PATCH 0009/1002] dma-debug: Put all hash-chain locks into the same lock class Alan Cox reported that lockdep runs out of its stack-trace entries with certain configs: BUG: MAX_STACK_TRACE_ENTRIES too low This happens because there are 1024 hash buckets, each with a separate lock. Lockdep puts each lock into a separate lock class and tracks them independently. But in reality we never take more than one of the buckets, so they really belong into a single lock-class. Annotate the has bucket lock init accordingly. [ Impact: reduce the lockdep footprint of dma-debug ] Reported-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> --- lib/dma-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index a9b6b5c9e0916..c9187fed0b938 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -716,7 +716,7 @@ void dma_debug_init(u32 num_entries) for (i = 0; i < HASH_SIZE; ++i) { INIT_LIST_HEAD(&dma_entry_hash[i].list); - dma_entry_hash[i].lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&dma_entry_hash[i].lock); } if (dma_debug_fs_init() != 0) { -- GitLab From aa93d632c496184e5b779dbcf961bf1c6ececf0b Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 5 May 2009 09:52:46 -0700 Subject: [PATCH 0010/1002] drm/i915: Require digital monitor on HDMI ports for detect HDMI and DVI both require DDC/EDID on monitors, so use that to know when a monitor is connected as the hot-plug pins are shared with SDVO and DisplayPort Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_hdmi.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4ea2a651b92c4..2495359ea8de5 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -31,6 +31,7 @@ #include "drmP.h" #include "drm.h" #include "drm_crtc.h" +#include "drm_edid.h" #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -129,20 +130,26 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, return true; } -static void -intel_hdmi_sink_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_hdmi_edid_detect(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; struct edid *edid = NULL; + enum drm_connector_status status = connector_status_disconnected; edid = drm_get_edid(&intel_output->base, &intel_output->ddc_bus->adapter); - if (edid != NULL) { - hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); - kfree(edid); + hdmi_priv->has_hdmi_sink = false; + if (edid) { + if (edid->digital) { + status = connector_status_connected; + hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); + } intel_output->base.display_info.raw_edid = NULL; + kfree(edid); } + return status; } static enum drm_connector_status @@ -154,11 +161,7 @@ igdng_hdmi_detect(struct drm_connector *connector) /* FIXME hotplug detect */ hdmi_priv->has_hdmi_sink = false; - intel_hdmi_sink_detect(connector); - if (hdmi_priv->has_hdmi_sink) - return connector_status_connected; - else - return connector_status_disconnected; + return intel_hdmi_edid_detect(connector); } static enum drm_connector_status @@ -201,10 +204,9 @@ intel_hdmi_detect(struct drm_connector *connector) return connector_status_unknown; } - if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) { - intel_hdmi_sink_detect(connector); - return connector_status_connected; - } else + if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) + return intel_hdmi_edid_detect(connector); + else return connector_status_disconnected; } -- GitLab From 98acd46f356e560c371c0e416d92e8e56be31804 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 14 Jun 2009 12:31:58 -0700 Subject: [PATCH 0011/1002] drm/i915: Apple DMI info has inconsistent SYS_VENDOR information Some machines say 'Apple Inc.' while others say 'Apple Computer, Inc'. Switch the test to just look for 'Apple' instead. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_lvds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f073ed8432e8f..345e5055f1c0f 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -456,7 +456,7 @@ static const struct dmi_system_id intel_no_lvds[] = { .callback = intel_no_lvds_dmi_callback, .ident = "Apple Mac Mini (Core series)", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_SYS_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), }, }, @@ -464,7 +464,7 @@ static const struct dmi_system_id intel_no_lvds[] = { .callback = intel_no_lvds_dmi_callback, .ident = "Apple Mac Mini (Core 2 series)", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_SYS_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), }, }, -- GitLab From b99e228d354cc1e7f19fb8b5f1297d493e309186 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 10 Jun 2009 19:08:16 -0700 Subject: [PATCH 0012/1002] drm/i915: check for CONFIG_PNP before using pnp function Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 5c1ceec49f5b6..daeae62e1c28b 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev) mchbar_addr = ((u64)temp_hi << 32) | temp_lo; /* If ACPI doesn't have it, assume we need to allocate it ourselves */ +#ifdef CONFIG_PNP if (mchbar_addr && pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { ret = 0; goto out_put; } +#endif /* Get some space for it */ ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, -- GitLab From f9c10a9b96a31b4a82a4fa807400c04f00284068 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 30 May 2009 12:16:25 -0700 Subject: [PATCH 0013/1002] drm/i915: Change I2C api to pass around i2c_adapters The existing API passed around intel_i2c_chan pointers, which are dependent on the i2c bit-banging algo. This precluded the driver from using outputs which use a different algo. Switching to the more general i2c_adpater allows the driver to support non bit-banging DDC. This also required moving the slave address into the output private structures. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/dvo.h | 4 +-- drivers/gpu/drm/i915/dvo_ch7017.c | 20 ++++++------ drivers/gpu/drm/i915/dvo_ch7xxx.c | 25 +++++++------- drivers/gpu/drm/i915/dvo_ivch.c | 21 ++++++------ drivers/gpu/drm/i915/dvo_sil164.c | 25 +++++++------- drivers/gpu/drm/i915/dvo_tfp410.c | 25 +++++++------- drivers/gpu/drm/i915/intel_drv.h | 11 +++---- drivers/gpu/drm/i915/intel_dvo.c | 16 ++++----- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_i2c.c | 16 ++++++--- drivers/gpu/drm/i915/intel_modes.c | 14 ++++---- drivers/gpu/drm/i915/intel_sdvo.c | 52 +++++++++++++++--------------- 12 files changed, 118 insertions(+), 113 deletions(-) diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index e747ac42fe3a9..288fc50627e2d 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h @@ -37,7 +37,7 @@ struct intel_dvo_device { /* GPIO register used for i2c bus to control this device */ u32 gpio; int slave_addr; - struct intel_i2c_chan *i2c_bus; + struct i2c_adapter *i2c_bus; const struct intel_dvo_dev_ops *dev_ops; void *dev_priv; @@ -52,7 +52,7 @@ struct intel_dvo_dev_ops { * Returns NULL if the device does not exist. */ bool (*init)(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus); + struct i2c_adapter *i2cbus); /* * Called to allow the output a chance to create properties after the diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 03d4b4973b02e..621815b531dbb 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c @@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) { - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[2]; u8 in_buf[2]; struct i2c_msg msgs[] = { { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 1, .buf = out_buf, }, { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD, .len = 1, .buf = in_buf, @@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) { - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); uint8_t out_buf[2]; struct i2c_msg msg = { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 2, .buf = out_buf, @@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) /** Probes for a CH7017 on the given bus and slave address. */ static bool ch7017_init(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus) + struct i2c_adapter *adapter) { + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); struct ch7017_priv *priv; uint8_t val; @@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, if (priv == NULL) return false; - dvo->i2c_bus = i2cbus; - dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->i2c_bus = adapter; dvo->dev_priv = priv; if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) @@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, val != CH7018_DEVICE_ID_VALUE && val != CH7019_DEVICE_ID_VALUE) { DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", - val, i2cbus->adapter.name,i2cbus->slave_addr); + val, i2cbus->adapter.name,dvo->slave_addr); goto fail; } diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index d2fd95dbd034b..a9b8962896801 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid) static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) { struct ch7xxx_priv *ch7xxx= dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[2]; u8 in_buf[2]; struct i2c_msg msgs[] = { { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 1, .buf = out_buf, }, { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD, .len = 1, .buf = in_buf, @@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) if (!ch7xxx->quiet) { DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; } @@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) { struct ch7xxx_priv *ch7xxx = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); uint8_t out_buf[2]; struct i2c_msg msg = { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 2, .buf = out_buf, @@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) if (!ch7xxx->quiet) { DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; } static bool ch7xxx_init(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus) + struct i2c_adapter *adapter) { /* this will detect the CH7xxx chip on the specified i2c bus */ struct ch7xxx_priv *ch7xxx; @@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, if (ch7xxx == NULL) return false; - dvo->i2c_bus = i2cbus; - dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->i2c_bus = adapter; dvo->dev_priv = ch7xxx; ch7xxx->quiet = true; @@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, name = ch7xxx_get_id(vendor); if (!name) { DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", - vendor, i2cbus->adapter.name, i2cbus->slave_addr); + vendor, adapter->name, dvo->slave_addr); goto out; } @@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, if (device != CH7xxx_DID) { DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", - vendor, i2cbus->adapter.name, i2cbus->slave_addr); + vendor, adapter->name, dvo->slave_addr); goto out; } diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 0c8d375e8e378..aa176f9921fe2 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo); static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) { struct ivch_priv *priv = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[1]; u8 in_buf[2]; struct i2c_msg msgs[] = { { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD, .len = 0, }, @@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) .buf = out_buf, }, { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD | I2C_M_NOSTART, .len = 2, .buf = in_buf, @@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) if (!priv->quiet) { DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; } @@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) { struct ivch_priv *priv = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[3]; struct i2c_msg msg = { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 3, .buf = out_buf, @@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) if (!priv->quiet) { DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) /** Probes the given bus and slave address for an ivch */ static bool ivch_init(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus) + struct i2c_adapter *adapter) { struct ivch_priv *priv; uint16_t temp; @@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, if (priv == NULL) return false; - dvo->i2c_bus = i2cbus; - dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->i2c_bus = adapter; dvo->dev_priv = priv; priv->quiet = true; diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 033a4bb070b2a..e1c1f7341e5cf 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c @@ -76,19 +76,20 @@ struct sil164_priv { static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) { struct sil164_priv *sil = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[2]; u8 in_buf[2]; struct i2c_msg msgs[] = { { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 1, .buf = out_buf, }, { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD, .len = 1, .buf = in_buf, @@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) if (!sil->quiet) { DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; } @@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) { struct sil164_priv *sil= dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); uint8_t out_buf[2]; struct i2c_msg msg = { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 2, .buf = out_buf, @@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) if (!sil->quiet) { DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) /* Silicon Image 164 driver for chip on i2c bus */ static bool sil164_init(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus) + struct i2c_adapter *adapter) { /* this will detect the SIL164 chip on the specified i2c bus */ struct sil164_priv *sil; @@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, if (sil == NULL) return false; - dvo->i2c_bus = i2cbus; - dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->i2c_bus = adapter; dvo->dev_priv = sil; sil->quiet = true; @@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, if (ch != (SIL164_VID & 0xff)) { DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", - ch, i2cbus->adapter.name, i2cbus->slave_addr); + ch, adapter->name, dvo->slave_addr); goto out; } @@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, if (ch != (SIL164_DID & 0xff)) { DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", - ch, i2cbus->adapter.name, i2cbus->slave_addr); + ch, adapter->name, dvo->slave_addr); goto out; } sil->quiet = false; diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 207fda806ebf8..9ecc907384ec3 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c @@ -101,19 +101,20 @@ struct tfp410_priv { static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) { struct tfp410_priv *tfp = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); u8 out_buf[2]; u8 in_buf[2]; struct i2c_msg msgs[] = { { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 1, .buf = out_buf, }, { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = I2C_M_RD, .len = 1, .buf = in_buf, @@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) if (!tfp->quiet) { DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; } @@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) { struct tfp410_priv *tfp = dvo->dev_priv; - struct intel_i2c_chan *i2cbus = dvo->i2c_bus; + struct i2c_adapter *adapter = dvo->i2c_bus; + struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); uint8_t out_buf[2]; struct i2c_msg msg = { - .addr = i2cbus->slave_addr, + .addr = dvo->slave_addr, .flags = 0, .len = 2, .buf = out_buf, @@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) if (!tfp->quiet) { DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", - addr, i2cbus->adapter.name, i2cbus->slave_addr); + addr, i2cbus->adapter.name, dvo->slave_addr); } return false; @@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr) /* Ti TFP410 driver for chip on i2c bus */ static bool tfp410_init(struct intel_dvo_device *dvo, - struct intel_i2c_chan *i2cbus) + struct i2c_adapter *adapter) { /* this will detect the tfp410 chip on the specified i2c bus */ struct tfp410_priv *tfp; @@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo, if (tfp == NULL) return false; - dvo->i2c_bus = i2cbus; - dvo->i2c_bus->slave_addr = dvo->slave_addr; + dvo->i2c_bus = adapter; dvo->dev_priv = tfp; tfp->quiet = true; if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", - id, i2cbus->adapter.name, i2cbus->slave_addr); + id, adapter->name, dvo->slave_addr); goto out; } if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", - id, i2cbus->adapter.name, i2cbus->slave_addr); + id, adapter->name, dvo->slave_addr); goto out; } tfp->quiet = false; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cd4b9c5f715e8..d89a2fed35af8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -65,7 +65,6 @@ struct intel_i2c_chan { u32 reg; /* GPIO reg */ struct i2c_adapter adapter; struct i2c_algo_bit_data algo; - u8 slave_addr; }; struct intel_framebuffer { @@ -79,8 +78,8 @@ struct intel_output { struct drm_encoder enc; int type; - struct intel_i2c_chan *i2c_bus; /* for control functions */ - struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ + struct i2c_adapter *i2c_bus; + struct i2c_adapter *ddc_bus; bool load_detect_temp; bool needs_tv_clock; void *dev_priv; @@ -104,9 +103,9 @@ struct intel_crtc { #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) -struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, - const char *name); -void intel_i2c_destroy(struct intel_i2c_chan *chan); +struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, + const char *name); +void intel_i2c_destroy(struct i2c_adapter *adapter); int intel_ddc_get_modes(struct intel_output *intel_output); extern bool intel_ddc_probe(struct intel_output *intel_output); void intel_i2c_quirk_set(struct drm_device *dev, bool enable); diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 1ee3007d6ec04..13bff20930e89 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev) { struct intel_output *intel_output; struct intel_dvo_device *dvo; - struct intel_i2c_chan *i2cbus = NULL; + struct i2c_adapter *i2cbus = NULL; int ret = 0; int i; - int gpio_inited = 0; int encoder_type = DRM_MODE_ENCODER_NONE; intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); if (!intel_output) @@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev) * It appears that everything is on GPIOE except for panels * on i830 laptops, which are on GPIOB (DVOA). */ - if (gpio_inited != gpio) { - if (i2cbus != NULL) - intel_i2c_destroy(i2cbus); - if (!(i2cbus = intel_i2c_create(dev, gpio, - gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { - continue; - } - gpio_inited = gpio; + if (i2cbus != NULL) + intel_i2c_destroy(i2cbus); + if (!(i2cbus = intel_i2c_create(dev, gpio, + gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { + continue; } if (dvo->dev_ops!= NULL) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2495359ea8de5..fbe96005fa1ef 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -139,7 +139,7 @@ intel_hdmi_edid_detect(struct drm_connector *connector) enum drm_connector_status status = connector_status_disconnected; edid = drm_get_edid(&intel_output->base, - &intel_output->ddc_bus->adapter); + intel_output->ddc_bus); hdmi_priv->has_hdmi_sink = false; if (edid) { if (edid->digital) { diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index f7061f68d050c..62b8bead7652c 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -124,6 +124,7 @@ static void set_data(void *data, int state_high) * @output: driver specific output device * @reg: GPIO reg to use * @name: name for this bus + * @slave_addr: slave address (if fixed) * * Creates and registers a new i2c bus with the Linux i2c layer, for use * in output probing and control (e.g. DDC or SDVO control functions). @@ -139,8 +140,8 @@ static void set_data(void *data, int state_high) * %GPIOH * see PRM for details on how these different busses are used. */ -struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, - const char *name) +struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, + const char *name) { struct intel_i2c_chan *chan; @@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, intel_i2c_quirk_set(dev, false); udelay(20); - return chan; + return &chan->adapter; out_free: kfree(chan); @@ -187,11 +188,16 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, * * Unregister the adapter from the i2c layer, then free the structure. */ -void intel_i2c_destroy(struct intel_i2c_chan *chan) +void intel_i2c_destroy(struct i2c_adapter *adapter) { - if (!chan) + struct intel_i2c_chan *chan; + + if (!adapter) return; + chan = container_of(adapter, + struct intel_i2c_chan, + adapter); i2c_del_adapter(&chan->adapter); kfree(chan); } diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index e0910fefce871..67e2f4632a245 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output) } }; - intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); - ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2); - intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); - + intel_i2c_quirk_set(intel_output->base.dev, true); + ret = i2c_transfer(intel_output->ddc_bus, msgs, 2); + intel_i2c_quirk_set(intel_output->base.dev, false); if (ret == 2) return true; @@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output) struct edid *edid; int ret = 0; - intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); - edid = drm_get_edid(&intel_output->base, - &intel_output->ddc_bus->adapter); - intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); + intel_i2c_quirk_set(intel_output->base.dev, true); + edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + intel_i2c_quirk_set(intel_output->base.dev, false); if (edid) { drm_mode_connector_update_edid_property(&intel_output->base, edid); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9a00adb3a5089..13c39c827ebf1 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -38,8 +38,8 @@ #undef SDVO_DEBUG #define I915_SDVO "i915_sdvo" struct intel_sdvo_priv { - struct intel_i2c_chan *i2c_bus; - int slaveaddr; + struct i2c_adapter *i2c_bus; + u8 slave_addr; /* Register for the SDVO device: SDVOB or SDVOC */ int output_device; @@ -146,13 +146,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, struct i2c_msg msgs[] = { { - .addr = sdvo_priv->i2c_bus->slave_addr, + .addr = sdvo_priv->slave_addr >> 1, .flags = 0, .len = 1, .buf = out_buf, }, { - .addr = sdvo_priv->i2c_bus->slave_addr, + .addr = sdvo_priv->slave_addr >> 1, .flags = I2C_M_RD, .len = 1, .buf = buf, @@ -162,7 +162,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, out_buf[0] = addr; out_buf[1] = 0; - if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) + if ((ret = i2c_transfer(sdvo_priv->i2c_bus, msgs, 2)) == 2) { *ch = buf[0]; return true; @@ -175,10 +175,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, u8 ch) { + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u8 out_buf[2]; struct i2c_msg msgs[] = { { - .addr = intel_output->i2c_bus->slave_addr, + .addr = sdvo_priv->slave_addr >> 1, .flags = 0, .len = 2, .buf = out_buf, @@ -188,7 +189,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, out_buf[0] = addr; out_buf[1] = ch; - if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) + if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1) { return true; } @@ -1371,7 +1372,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); edid = drm_get_edid(&intel_output->base, - &intel_output->ddc_bus->adapter); + intel_output->ddc_bus); if (edid != NULL) { sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); kfree(edid); @@ -1709,7 +1710,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (to_intel_output(connector)->ddc_bus == chan) { + if (to_intel_output(connector)->ddc_bus == &chan->adapter) { intel_output = to_intel_output(connector); break; } @@ -1723,7 +1724,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; struct i2c_algo_bit_data *algo_data; - struct i2c_algorithm *algo; + const struct i2c_algorithm *algo; algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; intel_output = @@ -1733,7 +1734,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, return -EINVAL; sdvo_priv = intel_output->dev_priv; - algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo; + algo = intel_output->i2c_bus->algo; intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); return algo->master_xfer(i2c_adap, msgs, num); @@ -1785,12 +1786,13 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) struct drm_connector *connector; struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; - struct intel_i2c_chan *i2cbus = NULL; - struct intel_i2c_chan *ddcbus = NULL; + struct i2c_adapter *i2cbus = NULL; + struct i2c_adapter *ddcbus = NULL; + int connector_type; u8 ch[0x40]; int i; - int encoder_type, output_id; + int encoder_type; u8 slave_addr; intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); @@ -1802,25 +1804,23 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) intel_output->type = INTEL_OUTPUT_SDVO; /* setup the DDC bus. */ - if (output_device == SDVOB) + if (output_device == SDVOB) { i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); - else + slave_addr = 0x38; + } else { i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); - + slave_addr = 0x39; + } + if (!i2cbus) goto err_inteloutput; slave_addr = intel_sdvo_get_slave_addr(dev, output_device); sdvo_priv->i2c_bus = i2cbus; + sdvo_priv->slave_addr = slave_addr; - if (output_device == SDVOB) { - output_id = 1; - } else { - output_id = 2; - } - sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1; sdvo_priv->output_device = output_device; - intel_output->i2c_bus = i2cbus; + intel_output->i2c_bus = sdvo_priv->i2c_bus; intel_output->dev_priv = sdvo_priv; /* Read the regs to test if we can talk to the device */ @@ -1843,8 +1843,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) goto err_i2c; intel_sdvo_i2c_bit_algo.functionality = - intel_output->i2c_bus->adapter.algo->functionality; - ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo; + intel_output->i2c_bus->algo->functionality; + ddcbus->algo = &intel_sdvo_i2c_bit_algo; intel_output->ddc_bus = ddcbus; /* In defaut case sdvo lvds is false */ -- GitLab From 308cd3a2e505b0d15f2852e8db5d648b60a6313b Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 14 Jun 2009 11:56:18 -0700 Subject: [PATCH 0014/1002] drm/i915: Clean up SDVO i2c handling Eliminate the copy of i2c_bus in sdvo_priv. Eliminate local copies of i2c_bus and ddcbus. Eliminate unused settings of slave_addr. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_sdvo.c | 54 ++++++++++++------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 13c39c827ebf1..f03473779feb4 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -38,7 +38,6 @@ #undef SDVO_DEBUG #define I915_SDVO "i915_sdvo" struct intel_sdvo_priv { - struct i2c_adapter *i2c_bus; u8 slave_addr; /* Register for the SDVO device: SDVOB or SDVOC */ @@ -162,7 +161,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, out_buf[0] = addr; out_buf[1] = 0; - if ((ret = i2c_transfer(sdvo_priv->i2c_bus, msgs, 2)) == 2) + if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2) { *ch = buf[0]; return true; @@ -1370,7 +1369,6 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; struct edid *edid = NULL; - intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); if (edid != NULL) { @@ -1550,7 +1548,6 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); - struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; struct drm_i915_private *dev_priv = connector->dev->dev_private; /* @@ -1558,8 +1555,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) * Assume that the preferred modes are * arranged in priority order. */ - /* set the bus switch and get the modes */ - intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); intel_ddc_get_modes(intel_output); if (list_empty(&connector->probed_modes) == false) return; @@ -1786,14 +1781,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) struct drm_connector *connector; struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; - struct i2c_adapter *i2cbus = NULL; - struct i2c_adapter *ddcbus = NULL; int connector_type; u8 ch[0x40]; int i; int encoder_type; - u8 slave_addr; intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); if (!intel_output) { @@ -1801,27 +1793,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) } sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); + sdvo_priv->output_device = output_device; + + intel_output->dev_priv = sdvo_priv; intel_output->type = INTEL_OUTPUT_SDVO; /* setup the DDC bus. */ - if (output_device == SDVOB) { - i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); - slave_addr = 0x38; - } else { - i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); - slave_addr = 0x39; - } - - if (!i2cbus) + if (output_device == SDVOB) + intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); + else + intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); + + if (!intel_output->i2c_bus) goto err_inteloutput; - slave_addr = intel_sdvo_get_slave_addr(dev, output_device); - sdvo_priv->i2c_bus = i2cbus; - sdvo_priv->slave_addr = slave_addr; + sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device); - sdvo_priv->output_device = output_device; - intel_output->i2c_bus = sdvo_priv->i2c_bus; - intel_output->dev_priv = sdvo_priv; + /* Save the bit-banging i2c functionality for use by the DDC wrapper */ + intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality; /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { @@ -1835,17 +1824,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) /* setup the DDC bus. */ if (output_device == SDVOB) - ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); + intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); else - ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); + intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); - if (ddcbus == NULL) + if (intel_output->ddc_bus == NULL) goto err_i2c; - intel_sdvo_i2c_bit_algo.functionality = - intel_output->i2c_bus->algo->functionality; - ddcbus->algo = &intel_sdvo_i2c_bit_algo; - intel_output->ddc_bus = ddcbus; + /* Wrap with our custom algo which switches to DDC mode */ + intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; /* In defaut case sdvo lvds is false */ sdvo_priv->is_lvds = false; @@ -1965,9 +1952,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) return true; err_i2c: - if (ddcbus != NULL) + if (intel_output->ddc_bus != NULL) intel_i2c_destroy(intel_output->ddc_bus); - intel_i2c_destroy(intel_output->i2c_bus); + if (intel_output->i2c_bus != NULL) + intel_i2c_destroy(intel_output->i2c_bus); err_inteloutput: kfree(intel_output); -- GitLab From c31c4ba3437d98efa19710e30d694a1cfdf87aa5 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 6 May 2009 11:48:58 -0700 Subject: [PATCH 0015/1002] drm/i915: add per-output hotplug callback for KMS This allows each output to deal with plug/unplug events as needed. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/i915_irq.c | 12 +++++++++++- drivers/gpu/drm/i915/intel_drv.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b86b7b7130c60..228546f6eaa4f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -232,7 +232,17 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, hotplug_work); struct drm_device *dev = dev_priv->dev; - + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + if (mode_config->num_connector) { + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); + + if (intel_output->hot_plug) + (*intel_output->hot_plug) (intel_output); + } + } /* Just fire off a uevent and let userspace tell us what to do */ drm_sysfs_hotplug_event(dev); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d89a2fed35af8..c5858792c8063 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -83,6 +83,7 @@ struct intel_output { bool load_detect_temp; bool needs_tv_clock; void *dev_priv; + void (*hot_plug)(struct intel_output *); }; struct intel_crtc { -- GitLab From a4fc5ed69817c73e32571ad7837bb707f9890009 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 7 Apr 2009 16:16:42 -0700 Subject: [PATCH 0016/1002] drm/i915: Add Display Port support Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/Makefile | 2 + drivers/gpu/drm/i915/i915_drv.h | 12 + drivers/gpu/drm/i915/i915_suspend.c | 34 +- drivers/gpu/drm/i915/intel_display.c | 107 ++- drivers/gpu/drm/i915/intel_dp.c | 1098 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.h | 144 ++++ drivers/gpu/drm/i915/intel_dp_i2c.c | 272 +++++++ drivers/gpu/drm/i915/intel_drv.h | 5 + 8 files changed, 1668 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_dp.c create mode 100644 drivers/gpu/drm/i915/intel_dp.h create mode 100644 drivers/gpu/drm/i915/intel_dp_i2c.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 51c5a050aa730..30d6b99fb3029 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ intel_crt.o \ intel_lvds.o \ intel_bios.o \ + intel_dp.o \ + intel_dp_i2c.o \ intel_hdmi.o \ intel_sdvo.o \ intel_modes.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a84f04e8439c..bb4c2d387b6c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -306,6 +306,17 @@ typedef struct drm_i915_private { u32 saveCURBPOS; u32 saveCURBBASE; u32 saveCURSIZE; + u32 saveDP_B; + u32 saveDP_C; + u32 saveDP_D; + u32 savePIPEA_GMCH_DATA_M; + u32 savePIPEB_GMCH_DATA_M; + u32 savePIPEA_GMCH_DATA_N; + u32 savePIPEB_GMCH_DATA_N; + u32 savePIPEA_DP_LINK_M; + u32 savePIPEB_DP_LINK_M; + u32 savePIPEA_DP_LINK_N; + u32 savePIPEB_DP_LINK_N; struct { struct drm_mm gtt_space; @@ -857,6 +868,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ IS_I915GM(dev))) #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) +#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a98e2831ed317..8d8e083d14ab2 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -322,6 +322,20 @@ int i915_save_state(struct drm_device *dev) dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); + /* Display Port state */ + if (SUPPORTS_INTEGRATED_DP(dev)) { + dev_priv->saveDP_B = I915_READ(DP_B); + dev_priv->saveDP_C = I915_READ(DP_C); + dev_priv->saveDP_D = I915_READ(DP_D); + dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M); + dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M); + dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N); + dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N); + dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M); + dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M); + dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N); + dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N); + } /* FIXME: save TV & SDVO state */ /* FBC state */ @@ -404,7 +418,19 @@ int i915_restore_state(struct drm_device *dev) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); } - + + /* Display port ratios (must be done before clock is set) */ + if (SUPPORTS_INTEGRATED_DP(dev)) { + I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); + I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); + I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); + I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); + I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); + I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); + I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); + I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); + } + /* Pipe & plane A info */ /* Prime the clock */ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { @@ -518,6 +544,12 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + /* Display Port state */ + if (SUPPORTS_INTEGRATED_DP(dev)) { + I915_WRITE(DP_B, dev_priv->saveDP_B); + I915_WRITE(DP_C, dev_priv->saveDP_C); + I915_WRITE(DP_D, dev_priv->saveDP_D); + } /* FIXME: restore TV & SDVO state */ /* FBC info */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c781621190..5af55aa0d7a65 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -29,6 +29,7 @@ #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" +#include "intel_dp.h" #include "drm_crtc_helper.h" @@ -135,10 +136,11 @@ struct intel_limit { #define INTEL_LIMIT_G4X_HDMI_DAC 5 #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 -#define INTEL_LIMIT_IGD_SDVO_DAC 8 -#define INTEL_LIMIT_IGD_LVDS 9 -#define INTEL_LIMIT_IGDNG_SDVO_DAC 10 -#define INTEL_LIMIT_IGDNG_LVDS 11 +#define INTEL_LIMIT_G4X_DISPLAY_PORT 8 +#define INTEL_LIMIT_IGD_SDVO_DAC 9 +#define INTEL_LIMIT_IGD_LVDS 10 +#define INTEL_LIMIT_IGDNG_SDVO_DAC 11 +#define INTEL_LIMIT_IGDNG_LVDS 12 /*The parameter is for SDVO on G4x platform*/ #define G4X_DOT_SDVO_MIN 25000 @@ -218,6 +220,25 @@ struct intel_limit { #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 +/*The parameter is for DISPLAY PORT on G4x platform*/ +#define G4X_DOT_DISPLAY_PORT_MIN 161670 +#define G4X_DOT_DISPLAY_PORT_MAX 227000 +#define G4X_N_DISPLAY_PORT_MIN 1 +#define G4X_N_DISPLAY_PORT_MAX 2 +#define G4X_M_DISPLAY_PORT_MIN 97 +#define G4X_M_DISPLAY_PORT_MAX 108 +#define G4X_M1_DISPLAY_PORT_MIN 0x10 +#define G4X_M1_DISPLAY_PORT_MAX 0x12 +#define G4X_M2_DISPLAY_PORT_MIN 0x05 +#define G4X_M2_DISPLAY_PORT_MAX 0x06 +#define G4X_P_DISPLAY_PORT_MIN 10 +#define G4X_P_DISPLAY_PORT_MAX 20 +#define G4X_P1_DISPLAY_PORT_MIN 1 +#define G4X_P1_DISPLAY_PORT_MAX 2 +#define G4X_P2_DISPLAY_PORT_SLOW 10 +#define G4X_P2_DISPLAY_PORT_FAST 10 +#define G4X_P2_DISPLAY_PORT_LIMIT 0 + /* IGDNG */ /* as we calculate clock using (register_value + 2) for N/M1/M2, so here the range value for them is (actual_value-2). @@ -256,6 +277,10 @@ static bool intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); +static bool +intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock); + static const intel_limit_t intel_limits[] = { { /* INTEL_LIMIT_I8XX_DVO_DAC */ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, @@ -389,6 +414,28 @@ static const intel_limit_t intel_limits[] = { }, .find_pll = intel_g4x_find_best_PLL, }, + { /* INTEL_LIMIT_G4X_DISPLAY_PORT */ + .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, + .max = G4X_DOT_DISPLAY_PORT_MAX }, + .vco = { .min = G4X_VCO_MIN, + .max = G4X_VCO_MAX}, + .n = { .min = G4X_N_DISPLAY_PORT_MIN, + .max = G4X_N_DISPLAY_PORT_MAX }, + .m = { .min = G4X_M_DISPLAY_PORT_MIN, + .max = G4X_M_DISPLAY_PORT_MAX }, + .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, + .max = G4X_M1_DISPLAY_PORT_MAX }, + .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, + .max = G4X_M2_DISPLAY_PORT_MAX }, + .p = { .min = G4X_P_DISPLAY_PORT_MIN, + .max = G4X_P_DISPLAY_PORT_MAX }, + .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, + .max = G4X_P1_DISPLAY_PORT_MAX}, + .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, + .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, + .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, + .find_pll = intel_find_pll_g4x_dp, + }, { /* INTEL_LIMIT_IGD_SDVO */ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, @@ -478,6 +525,8 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; + } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { + limit = &intel_limits[INTEL_LIMIT_G4X_DISPLAY_PORT]; } else /* The option is for other outputs */ limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; @@ -764,6 +813,35 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, return found; } +/* DisplayPort has only two frequencies, 162MHz and 270MHz */ +static bool +intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, + int target, int refclk, intel_clock_t *best_clock) +{ + intel_clock_t clock; + if (target < 200000) { + clock.dot = 161670; + clock.p = 20; + clock.p1 = 2; + clock.p2 = 10; + clock.n = 0x01; + clock.m = 97; + clock.m1 = 0x10; + clock.m2 = 0x05; + } else { + clock.dot = 270000; + clock.p = 10; + clock.p1 = 1; + clock.p2 = 10; + clock.n = 0x02; + clock.m = 108; + clock.m1 = 0x12; + clock.m2 = 0x06; + } + memcpy(best_clock, &clock, sizeof(intel_clock_t)); + return true; +} + void intel_wait_for_vblank(struct drm_device *dev) { @@ -1541,7 +1619,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, intel_clock_t clock; u32 dpll = 0, fp = 0, dspcntr, pipeconf; bool ok, is_sdvo = false, is_dvo = false; - bool is_crt = false, is_lvds = false, is_tv = false; + bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; const intel_limit_t *limit; @@ -1585,6 +1663,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_ANALOG: is_crt = true; break; + case INTEL_OUTPUT_DISPLAYPORT: + is_dp = true; + break; } num_outputs++; @@ -1600,6 +1681,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } else { refclk = 48000; } + /* * Returns a set of divisors for the desired target clock with the given @@ -1662,6 +1744,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, else if (IS_IGDNG(dev)) dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; } + if (is_dp) + dpll |= DPLL_DVO_HIGH_SPEED; /* compute bitmask from p1 value */ if (IS_IGD(dev)) @@ -1809,6 +1893,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(lvds_reg, lvds); I915_READ(lvds_reg); } + if (is_dp) + intel_dp_set_m_n(crtc, mode, adjusted_mode); I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll); @@ -2475,6 +2561,8 @@ static void intel_setup_outputs(struct drm_device *dev) found = intel_sdvo_init(dev, SDVOB); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOB); + if (!found && SUPPORTS_INTEGRATED_DP(dev)) + intel_dp_init(dev, DP_B); } /* Before G4X SDVOC doesn't have its own detect register */ @@ -2487,7 +2575,11 @@ static void intel_setup_outputs(struct drm_device *dev) found = intel_sdvo_init(dev, SDVOC); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOC); + if (!found && SUPPORTS_INTEGRATED_DP(dev)) + intel_dp_init(dev, DP_C); } + if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) + intel_dp_init(dev, DP_D); } else intel_dvo_init(dev); @@ -2530,6 +2622,11 @@ static void intel_setup_outputs(struct drm_device *dev) (1 << 1)); clone_mask = (1 << INTEL_OUTPUT_TVOUT); break; + case INTEL_OUTPUT_DISPLAYPORT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); + break; } encoder->possible_crtcs = crtc_mask; encoder->possible_clones = intel_connector_clones(dev, clone_mask); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c new file mode 100644 index 0000000000000..c57cdab4f4a6f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -0,0 +1,1098 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Keith Packard <keithp@keithp.com> + * + */ + +#include <linux/i2c.h> +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "intel_dp.h" + +#define DP_LINK_STATUS_SIZE 6 +#define DP_LINK_CHECK_TIMEOUT (10 * 1000) + +#define DP_LINK_CONFIGURATION_SIZE 9 + +struct intel_dp_priv { + uint32_t output_reg; + uint32_t DP; + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; + uint32_t save_DP; + uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE]; + bool has_audio; + uint8_t link_bw; + uint8_t lane_count; + uint8_t dpcd[4]; + struct intel_output *intel_output; + struct i2c_adapter adapter; + struct i2c_algo_dp_aux_data algo; +}; + +static void +intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]); + +static void +intel_dp_link_down(struct intel_output *intel_output, uint32_t DP); + +static int +intel_dp_max_lane_count(struct intel_output *intel_output) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + int max_lane_count = 4; + + if (dp_priv->dpcd[0] >= 0x11) { + max_lane_count = dp_priv->dpcd[2] & 0x1f; + switch (max_lane_count) { + case 1: case 2: case 4: + break; + default: + max_lane_count = 4; + } + } + return max_lane_count; +} + +static int +intel_dp_max_link_bw(struct intel_output *intel_output) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + int max_link_bw = dp_priv->dpcd[1]; + + switch (max_link_bw) { + case DP_LINK_BW_1_62: + case DP_LINK_BW_2_7: + break; + default: + max_link_bw = DP_LINK_BW_1_62; + break; + } + return max_link_bw; +} + +static int +intel_dp_link_clock(uint8_t link_bw) +{ + if (link_bw == DP_LINK_BW_2_7) + return 270000; + else + return 162000; +} + +/* I think this is a fiction */ +static int +intel_dp_link_required(int pixel_clock) +{ + return pixel_clock * 3; +} + +static int +intel_dp_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct intel_output *intel_output = to_intel_output(connector); + int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); + int max_lanes = intel_dp_max_lane_count(intel_output); + + if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) + return MODE_CLOCK_HIGH; + + if (mode->clock < 10000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static uint32_t +pack_aux(uint8_t *src, int src_bytes) +{ + int i; + uint32_t v = 0; + + if (src_bytes > 4) + src_bytes = 4; + for (i = 0; i < src_bytes; i++) + v |= ((uint32_t) src[i]) << ((3-i) * 8); + return v; +} + +static void +unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) +{ + int i; + if (dst_bytes > 4) + dst_bytes = 4; + for (i = 0; i < dst_bytes; i++) + dst[i] = src >> ((3-i) * 8); +} + +static int +intel_dp_aux_ch(struct intel_output *intel_output, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_size) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + uint32_t output_reg = dp_priv->output_reg; + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t ch_ctl = output_reg + 0x10; + uint32_t ch_data = ch_ctl + 4; + int i; + int recv_bytes; + uint32_t ctl; + uint32_t status; + + /* Load the send data into the aux channel data registers */ + for (i = 0; i < send_bytes; i += 4) { + uint32_t d = pack_aux(send + i, send_bytes - i);; + + I915_WRITE(ch_data + i, d); + } + + /* The clock divider is based off the hrawclk, + * and would like to run at 2MHz. The 133 below assumes + * a 266MHz hrawclk; need to figure out how we're supposed + * to know what hrawclk is... + */ + ctl = (DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_1600us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (133 << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + + /* Send the command and wait for it to complete */ + I915_WRITE(ch_ctl, ctl); + (void) I915_READ(ch_ctl); + for (;;) { + udelay(100); + status = I915_READ(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + } + + /* Clear done status and any errors */ + I915_WRITE(ch_ctl, (ctl | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR)); + (void) I915_READ(ch_ctl); + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { + printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); + return -1; + } + + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_RECEIVE_ERROR)) { + printk(KERN_ERR "dp_aux_ch error status 0x%08x\n", status); + return -1; + } + + /* Unload any bytes sent back from the other side */ + recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> + DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); + + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + for (i = 0; i < recv_bytes; i += 4) { + uint32_t d = I915_READ(ch_data + i); + + unpack_aux(d, recv + i, recv_bytes - i); + } + + return recv_bytes; +} + +/* Write data to the aux channel in native mode */ +static int +intel_dp_aux_native_write(struct intel_output *intel_output, + uint16_t address, uint8_t *send, int send_bytes) +{ + int ret; + uint8_t msg[20]; + int msg_bytes; + uint8_t ack; + + if (send_bytes > 16) + return -1; + msg[0] = AUX_NATIVE_WRITE << 4; + msg[1] = address >> 8; + msg[2] = address; + msg[3] = send_bytes - 1; + memcpy(&msg[4], send, send_bytes); + msg_bytes = send_bytes + 4; + for (;;) { + ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1); + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + break; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -1; + } + return send_bytes; +} + +/* Write a single byte to the aux channel in native mode */ +static int +intel_dp_aux_native_write_1(struct intel_output *intel_output, + uint16_t address, uint8_t byte) +{ + return intel_dp_aux_native_write(intel_output, address, &byte, 1); +} + +/* read bytes from a native aux channel */ +static int +intel_dp_aux_native_read(struct intel_output *intel_output, + uint16_t address, uint8_t *recv, int recv_bytes) +{ + uint8_t msg[4]; + int msg_bytes; + uint8_t reply[20]; + int reply_bytes; + uint8_t ack; + int ret; + + msg[0] = AUX_NATIVE_READ << 4; + msg[1] = address >> 8; + msg[2] = address & 0xff; + msg[3] = recv_bytes - 1; + + msg_bytes = 4; + reply_bytes = recv_bytes + 1; + + for (;;) { + ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, + reply, reply_bytes); + if (ret <= 0) + return ret; + ack = reply[0]; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { + memcpy(recv, reply + 1, ret - 1); + return ret - 1; + } + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -1; + } +} + +static int +intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_bytes) +{ + struct intel_dp_priv *dp_priv = container_of(adapter, + struct intel_dp_priv, + adapter); + struct intel_output *intel_output = dp_priv->intel_output; + + return intel_dp_aux_ch(intel_output, + send, send_bytes, recv, recv_bytes); +} + +static int +intel_dp_i2c_init(struct intel_output *intel_output, const char *name) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + DRM_ERROR("i2c_init %s\n", name); + dp_priv->algo.running = false; + dp_priv->algo.address = 0; + dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch; + + memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter)); + dp_priv->adapter.owner = THIS_MODULE; + dp_priv->adapter.class = I2C_CLASS_DDC; + strncpy (dp_priv->adapter.name, name, sizeof dp_priv->adapter.name - 1); + dp_priv->adapter.name[sizeof dp_priv->adapter.name - 1] = '\0'; + dp_priv->adapter.algo_data = &dp_priv->algo; + dp_priv->adapter.dev.parent = &intel_output->base.kdev; + + return i2c_dp_aux_add_bus(&dp_priv->adapter); +} + +static bool +intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + int lane_count, clock; + int max_lane_count = intel_dp_max_lane_count(intel_output); + int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0; + static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; + + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { + for (clock = 0; clock <= max_clock; clock++) { + int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; + + if (intel_dp_link_required(mode->clock) <= link_avail) { + dp_priv->link_bw = bws[clock]; + dp_priv->lane_count = lane_count; + adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); + printk(KERN_ERR "link bw %02x lane count %d clock %d\n", + dp_priv->link_bw, dp_priv->lane_count, + adjusted_mode->clock); + return true; + } + } + } + return false; +} + +struct intel_dp_m_n { + uint32_t tu; + uint32_t gmch_m; + uint32_t gmch_n; + uint32_t link_m; + uint32_t link_n; +}; + +static void +intel_reduce_ratio(uint32_t *num, uint32_t *den) +{ + while (*num > 0xffffff || *den > 0xffffff) { + *num >>= 1; + *den >>= 1; + } +} + +static void +intel_dp_compute_m_n(int bytes_per_pixel, + int nlanes, + int pixel_clock, + int link_clock, + struct intel_dp_m_n *m_n) +{ + m_n->tu = 64; + m_n->gmch_m = pixel_clock * bytes_per_pixel; + m_n->gmch_n = link_clock * nlanes; + intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); + m_n->link_m = pixel_clock; + m_n->link_n = link_clock; + intel_reduce_ratio(&m_n->link_m, &m_n->link_n); +} + +void +intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int lane_count = 4; + struct intel_dp_m_n m_n; + + /* + * Find the lane count in the intel_output private + */ + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + if (!connector->encoder || connector->encoder->crtc != crtc) + continue; + + if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { + lane_count = dp_priv->lane_count; + break; + } + } + + /* + * Compute the GMCH and Link ratios. The '3' here is + * the number of bytes_per_pixel post-LUT, which we always + * set up for 8-bits of R/G/B, or 3 bytes total. + */ + intel_dp_compute_m_n(3, lane_count, + mode->clock, adjusted_mode->clock, &m_n); + + if (intel_crtc->pipe == 0) { + I915_WRITE(PIPEA_GMCH_DATA_M, + ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | + m_n.gmch_m); + I915_WRITE(PIPEA_GMCH_DATA_N, + m_n.gmch_n); + I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); + I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); + } else { + I915_WRITE(PIPEB_GMCH_DATA_M, + ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | + m_n.gmch_m); + I915_WRITE(PIPEB_GMCH_DATA_N, + m_n.gmch_n); + I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); + I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); + } +} + +static void +intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + struct drm_crtc *crtc = intel_output->enc.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + dp_priv->DP = (DP_LINK_TRAIN_OFF | + DP_VOLTAGE_0_4 | + DP_PRE_EMPHASIS_0 | + DP_SYNC_VS_HIGH | + DP_SYNC_HS_HIGH); + + switch (dp_priv->lane_count) { + case 1: + dp_priv->DP |= DP_PORT_WIDTH_1; + break; + case 2: + dp_priv->DP |= DP_PORT_WIDTH_2; + break; + case 4: + dp_priv->DP |= DP_PORT_WIDTH_4; + break; + } + if (dp_priv->has_audio) + dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE; + + memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); + dp_priv->link_configuration[0] = dp_priv->link_bw; + dp_priv->link_configuration[1] = dp_priv->lane_count; + + /* + * Check for DPCD version > 1.1, + * enable enahanced frame stuff in that case + */ + if (dp_priv->dpcd[0] >= 0x11) { + dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + dp_priv->DP |= DP_ENHANCED_FRAMING; + } + + if (intel_crtc->pipe == 1) + dp_priv->DP |= DP_PIPEB_SELECT; +} + + +static void +intel_dp_dpms(struct drm_encoder *encoder, int mode) +{ + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t dp_reg = I915_READ(dp_priv->output_reg); + + if (mode != DRM_MODE_DPMS_ON) { + if (dp_reg & DP_PORT_EN) + intel_dp_link_down(intel_output, dp_priv->DP); + } else { + if (!(dp_reg & DP_PORT_EN)) + intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); + } +} + +/* + * Fetch AUX CH registers 0x202 - 0x207 which contain + * link status information + */ +static bool +intel_dp_get_link_status(struct intel_output *intel_output, + uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + int ret; + + ret = intel_dp_aux_native_read(intel_output, + DP_LANE0_1_STATUS, + link_status, DP_LINK_STATUS_SIZE); + if (ret != DP_LINK_STATUS_SIZE) + return false; + return true; +} + +static uint8_t +intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int r) +{ + return link_status[r - DP_LANE0_1_STATUS]; +} + +static void +intel_dp_save(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + dp_priv->save_DP = I915_READ(dp_priv->output_reg); + intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET, + dp_priv->save_link_configuration, + sizeof (dp_priv->save_link_configuration)); +} + +static uint8_t +intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + uint8_t l = intel_dp_link_status(link_status, i); + + return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; +} + +static uint8_t +intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + uint8_t l = intel_dp_link_status(link_status, i); + + return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; +} + + +#if 0 +static char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +static char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; +static char *link_train_names[] = { + "pattern 1", "pattern 2", "idle", "off" +}; +#endif + +/* + * These are source-specific values; current Intel hardware supports + * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB + */ +#define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 + +static uint8_t +intel_dp_pre_emphasis_max(uint8_t voltage_swing) +{ + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } +} + +static void +intel_get_adjust_train(struct intel_output *intel_output, + uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane_count, + uint8_t train_set[4]) +{ + uint8_t v = 0; + uint8_t p = 0; + int lane; + + for (lane = 0; lane < lane_count; lane++) { + uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); + uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + if (v >= I830_DP_VOLTAGE_MAX) + v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; + + if (p >= intel_dp_pre_emphasis_max(v)) + p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + for (lane = 0; lane < 4; lane++) + train_set[lane] = v | p; +} + +static uint32_t +intel_dp_signal_levels(uint8_t train_set, int lane_count) +{ + uint32_t signal_levels = 0; + + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + default: + signal_levels |= DP_VOLTAGE_0_4; + break; + case DP_TRAIN_VOLTAGE_SWING_600: + signal_levels |= DP_VOLTAGE_0_6; + break; + case DP_TRAIN_VOLTAGE_SWING_800: + signal_levels |= DP_VOLTAGE_0_8; + break; + case DP_TRAIN_VOLTAGE_SWING_1200: + signal_levels |= DP_VOLTAGE_1_2; + break; + } + switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { + case DP_TRAIN_PRE_EMPHASIS_0: + default: + signal_levels |= DP_PRE_EMPHASIS_0; + break; + case DP_TRAIN_PRE_EMPHASIS_3_5: + signal_levels |= DP_PRE_EMPHASIS_3_5; + break; + case DP_TRAIN_PRE_EMPHASIS_6: + signal_levels |= DP_PRE_EMPHASIS_6; + break; + case DP_TRAIN_PRE_EMPHASIS_9_5: + signal_levels |= DP_PRE_EMPHASIS_9_5; + break; + } + return signal_levels; +} + +static uint8_t +intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_LANE0_1_STATUS + (lane >> 1); + int s = (lane & 1) * 4; + uint8_t l = intel_dp_link_status(link_status, i); + + return (l >> s) & 0xf; +} + +/* Check for clock recovery is done on all channels */ +static bool +intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) +{ + int lane; + uint8_t lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = intel_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return false; + } + return true; +} + +/* Check to see if channel eq is done on all channels */ +#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ + DP_LANE_CHANNEL_EQ_DONE|\ + DP_LANE_SYMBOL_LOCKED) +static bool +intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) +{ + uint8_t lane_align; + uint8_t lane_status; + int lane; + + lane_align = intel_dp_link_status(link_status, + DP_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return false; + for (lane = 0; lane < lane_count; lane++) { + lane_status = intel_get_lane_status(link_status, lane); + if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) + return false; + } + return true; +} + +static bool +intel_dp_set_link_train(struct intel_output *intel_output, + uint32_t dp_reg_value, + uint8_t dp_train_pat, + uint8_t train_set[4], + bool first) +{ + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + int ret; + + I915_WRITE(dp_priv->output_reg, dp_reg_value); + POSTING_READ(dp_priv->output_reg); + if (first) + intel_wait_for_vblank(dev); + + intel_dp_aux_native_write_1(intel_output, + DP_TRAINING_PATTERN_SET, + dp_train_pat); + + ret = intel_dp_aux_native_write(intel_output, + DP_TRAINING_LANE0_SET, train_set, 4); + if (ret != 4) + return false; + + return true; +} + +static void +intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]) +{ + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + uint8_t train_set[4]; + uint8_t link_status[DP_LINK_STATUS_SIZE]; + int i; + uint8_t voltage; + bool clock_recovery = false; + bool channel_eq = false; + bool first = true; + int tries; + + /* Write the link configuration data */ + intel_dp_aux_native_write(intel_output, 0x100, + link_configuration, DP_LINK_CONFIGURATION_SIZE); + + DP |= DP_PORT_EN; + DP &= ~DP_LINK_TRAIN_MASK; + memset(train_set, 0, 4); + voltage = 0xff; + tries = 0; + clock_recovery = false; + for (;;) { + /* Use train_set[0] to set the voltage and pre emphasis values */ + uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); + DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; + + if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1, + DP_TRAINING_PATTERN_1, train_set, first)) + break; + first = false; + /* Set training pattern 1 */ + + udelay(100); + if (!intel_dp_get_link_status(intel_output, link_status)) + break; + + if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) { + clock_recovery = true; + break; + } + + /* Check to see if we've tried the max voltage */ + for (i = 0; i < dp_priv->lane_count; i++) + if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + if (i == dp_priv->lane_count) + break; + + /* Check to see if we've tried the same voltage 5 times */ + if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++tries; + if (tries == 5) + break; + } else + tries = 0; + voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Compute new train_set as requested by target */ + intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); + } + + /* channel equalization */ + tries = 0; + channel_eq = false; + for (;;) { + /* Use train_set[0] to set the voltage and pre emphasis values */ + uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); + DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; + + /* channel eq pattern */ + if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2, + DP_TRAINING_PATTERN_2, train_set, + false)) + break; + + udelay(400); + if (!intel_dp_get_link_status(intel_output, link_status)) + break; + + if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) { + channel_eq = true; + break; + } + + /* Try 5 times */ + if (tries > 5) + break; + + /* Compute new train_set as requested by target */ + intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); + ++tries; + } + + I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF); + POSTING_READ(dp_priv->output_reg); + intel_dp_aux_native_write_1(intel_output, + DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); +} + +static void +intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) +{ + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); + POSTING_READ(dp_priv->output_reg); +} + +static void +intel_dp_restore(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + if (dp_priv->save_DP & DP_PORT_EN) + intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration); + else + intel_dp_link_down(intel_output, dp_priv->save_DP); +} + +#if 0 +/* + * According to DP spec + * 5.1.2: + * 1. Read DPCD + * 2. Configure link according to Receiver Capabilities + * 3. Use Link Training from 2.5.3.3 and 3.5.1.3 + * 4. Check link status on receipt of hot-plug interrupt + */ + +static void +intel_dp_check_link_status(struct intel_output *intel_output) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + uint8_t link_status[DP_LINK_STATUS_SIZE]; + + if (!intel_output->enc.crtc) + return; + + if (!intel_dp_get_link_status(intel_output, link_status)) { + intel_dp_link_down(intel_output, dp_priv->DP); + return; + } + + if (!intel_channel_eq_ok(link_status, dp_priv->lane_count)) + intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); +} +#endif + +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. + * + * \return true if DP port is connected. + * \return false if DP port is disconnected. + */ +static enum drm_connector_status +intel_dp_detect(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + struct drm_device *dev = intel_output->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + uint32_t temp, bit; + enum drm_connector_status status; + + dp_priv->has_audio = false; + + temp = I915_READ(PORT_HOTPLUG_EN); + + I915_WRITE(PORT_HOTPLUG_EN, + temp | + DPB_HOTPLUG_INT_EN | + DPC_HOTPLUG_INT_EN | + DPD_HOTPLUG_INT_EN); + + POSTING_READ(PORT_HOTPLUG_EN); + + switch (dp_priv->output_reg) { + case DP_B: + bit = DPB_HOTPLUG_INT_STATUS; + break; + case DP_C: + bit = DPC_HOTPLUG_INT_STATUS; + break; + case DP_D: + bit = DPD_HOTPLUG_INT_STATUS; + break; + default: + return connector_status_unknown; + } + + temp = I915_READ(PORT_HOTPLUG_STAT); + + if ((temp & bit) == 0) + return connector_status_disconnected; + + status = connector_status_disconnected; + if (intel_dp_aux_native_read(intel_output, + 0x000, dp_priv->dpcd, + sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) + { + if (dp_priv->dpcd[0] != 0) + status = connector_status_connected; + } + return status; +} + +static int intel_dp_get_modes(struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + /* We should parse the EDID data and find out if it has an audio sink + */ + + return intel_ddc_get_modes(intel_output); +} + +static void +intel_dp_destroy (struct drm_connector *connector) +{ + struct intel_output *intel_output = to_intel_output(connector); + + if (intel_output->i2c_bus) + intel_i2c_destroy(intel_output->i2c_bus); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(intel_output); +} + +static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { + .dpms = intel_dp_dpms, + .mode_fixup = intel_dp_mode_fixup, + .prepare = intel_encoder_prepare, + .mode_set = intel_dp_mode_set, + .commit = intel_encoder_commit, +}; + +static const struct drm_connector_funcs intel_dp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .save = intel_dp_save, + .restore = intel_dp_restore, + .detect = intel_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = intel_dp_destroy, +}; + +static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { + .get_modes = intel_dp_get_modes, + .mode_valid = intel_dp_mode_valid, + .best_encoder = intel_best_encoder, +}; + +static void intel_dp_enc_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_funcs intel_dp_enc_funcs = { + .destroy = intel_dp_enc_destroy, +}; + +void +intel_dp_init(struct drm_device *dev, int output_reg) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_connector *connector; + struct intel_output *intel_output; + struct intel_dp_priv *dp_priv; + + intel_output = kcalloc(sizeof(struct intel_output) + + sizeof(struct intel_dp_priv), 1, GFP_KERNEL); + if (!intel_output) + return; + + dp_priv = (struct intel_dp_priv *)(intel_output + 1); + + connector = &intel_output->base; + drm_connector_init(dev, connector, &intel_dp_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); + + intel_output->type = INTEL_OUTPUT_DISPLAYPORT; + + connector->interlace_allowed = true; + connector->doublescan_allowed = 0; + + dp_priv->intel_output = intel_output; + dp_priv->output_reg = output_reg; + dp_priv->has_audio = false; + intel_output->dev_priv = dp_priv; + + drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs); + + drm_mode_connector_attach_encoder(&intel_output->base, + &intel_output->enc); + drm_sysfs_connector_add(connector); + + /* Set up the DDC bus. */ + intel_dp_i2c_init(intel_output, + (output_reg == DP_B) ? "DPDDC-B" : + (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); + intel_output->ddc_bus = &dp_priv->adapter; + + /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written + * 0xd. Failure to do so will result in spurious interrupts being + * generated on the port when a cable is not attached. + */ + if (IS_G4X(dev) && !IS_GM45(dev)) { + u32 temp = I915_READ(PEG_BAND_GAP_DATA); + I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); + } +} diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h new file mode 100644 index 0000000000000..2b38054d3b6d4 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.h @@ -0,0 +1,144 @@ +/* + * Copyright © 2008 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _INTEL_DP_H_ +#define _INTEL_DP_H_ + +/* From the VESA DisplayPort spec */ + +#define AUX_NATIVE_WRITE 0x8 +#define AUX_NATIVE_READ 0x9 +#define AUX_I2C_WRITE 0x0 +#define AUX_I2C_READ 0x1 +#define AUX_I2C_STATUS 0x2 +#define AUX_I2C_MOT 0x4 + +#define AUX_NATIVE_REPLY_ACK (0x0 << 4) +#define AUX_NATIVE_REPLY_NACK (0x1 << 4) +#define AUX_NATIVE_REPLY_DEFER (0x2 << 4) +#define AUX_NATIVE_REPLY_MASK (0x3 << 4) + +#define AUX_I2C_REPLY_ACK (0x0 << 6) +#define AUX_I2C_REPLY_NACK (0x1 << 6) +#define AUX_I2C_REPLY_DEFER (0x2 << 6) +#define AUX_I2C_REPLY_MASK (0x3 << 6) + +/* AUX CH addresses */ +#define DP_LINK_BW_SET 0x100 +# define DP_LINK_BW_1_62 0x06 +# define DP_LINK_BW_2_7 0x0a + +#define DP_LANE_COUNT_SET 0x101 +# define DP_LANE_COUNT_MASK 0x0f +# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) + +#define DP_TRAINING_PATTERN_SET 0x102 + +# define DP_TRAINING_PATTERN_DISABLE 0 +# define DP_TRAINING_PATTERN_1 1 +# define DP_TRAINING_PATTERN_2 2 +# define DP_TRAINING_PATTERN_MASK 0x3 + +# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) +# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) +# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) +# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) +# define DP_LINK_QUAL_PATTERN_MASK (3 << 2) + +# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) +# define DP_LINK_SCRAMBLING_DISABLE (1 << 5) + +# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) +# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) +# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) +# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) + +#define DP_TRAINING_LANE0_SET 0x103 +#define DP_TRAINING_LANE1_SET 0x104 +#define DP_TRAINING_LANE2_SET 0x105 +#define DP_TRAINING_LANE3_SET 0x106 + +# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 +# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 +# define DP_TRAIN_MAX_SWING_REACHED (1 << 2) +# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) +# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) +# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) +# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) + +# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) +# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) +# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) +# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) +# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) + +# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 +# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) + +#define DP_DOWNSPREAD_CTRL 0x107 +# define DP_SPREAD_AMP_0_5 (1 << 4) + +#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 +# define DP_SET_ANSI_8B10B (1 << 0) + +#define DP_LANE0_1_STATUS 0x202 +#define DP_LANE2_3_STATUS 0x203 + +# define DP_LANE_CR_DONE (1 << 0) +# define DP_LANE_CHANNEL_EQ_DONE (1 << 1) +# define DP_LANE_SYMBOL_LOCKED (1 << 2) + +#define DP_LANE_ALIGN_STATUS_UPDATED 0x204 + +#define DP_INTERLANE_ALIGN_DONE (1 << 0) +#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) +#define DP_LINK_STATUS_UPDATED (1 << 7) + +#define DP_SINK_STATUS 0x205 + +#define DP_RECEIVE_PORT_0_STATUS (1 << 0) +#define DP_RECEIVE_PORT_1_STATUS (1 << 1) + +#define DP_ADJUST_REQUEST_LANE0_1 0x206 +#define DP_ADJUST_REQUEST_LANE2_3 0x207 + +#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 +#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 +#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 +#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 + +struct i2c_algo_dp_aux_data { + bool running; + u16 address; + int (*aux_ch) (struct i2c_adapter *adapter, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_bytes); +}; + +int +i2c_dp_aux_add_bus(struct i2c_adapter *adapter); + +#endif /* _INTEL_DP_H_ */ diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c new file mode 100644 index 0000000000000..4e60f14b1a6db --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c @@ -0,0 +1,272 @@ +/* + * Copyright © 2009 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/i2c.h> +#include "intel_dp.h" + +/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ + +#define MODE_I2C_START 1 +#define MODE_I2C_WRITE 2 +#define MODE_I2C_READ 4 +#define MODE_I2C_STOP 8 + +static int +i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + uint16_t address = algo_data->address; + uint8_t msg[5]; + uint8_t reply[2]; + int msg_bytes; + int reply_bytes; + int ret; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[0] = AUX_I2C_READ << 4; + else + msg[0] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[0] |= AUX_I2C_MOT << 4; + + msg[1] = address >> 8; + msg[2] = address; + + switch (mode) { + case MODE_I2C_WRITE: + msg[3] = 0; + msg[4] = write_byte; + msg_bytes = 5; + reply_bytes = 1; + break; + case MODE_I2C_READ: + msg[3] = 0; + msg_bytes = 4; + reply_bytes = 2; + break; + default: + msg_bytes = 3; + reply_bytes = 1; + break; + } + + for (;;) { + ret = (*algo_data->aux_ch)(adapter, + msg, msg_bytes, + reply, reply_bytes); + if (ret < 0) { + printk(KERN_ERR "aux_ch failed %d\n", ret); + return ret; + } + switch (reply[0] & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) { + *read_byte = reply[1]; + } + return reply_bytes - 1; + case AUX_I2C_REPLY_NACK: + printk(KERN_ERR "aux_ch nack\n"); + return -EREMOTEIO; + case AUX_I2C_REPLY_DEFER: + printk(KERN_ERR "aux_ch defer\n"); + udelay(100); + break; + default: + printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]); + return -EREMOTEIO; + } + } +} + +/* + * I2C over AUX CH + */ + +/* + * Send the address. If the I2C link is running, this 'restarts' + * the connection with the new address, this is used for doing + * a write followed by a read (as needed for DDC) + */ +static int +i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int mode = MODE_I2C_START; + int ret; + + if (reading) + mode |= MODE_I2C_READ; + else + mode |= MODE_I2C_WRITE; + algo_data->address = address; + algo_data->running = true; + ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); + return ret; +} + +/* + * Stop the I2C transaction. This closes out the link, sending + * a bare address packet with the MOT bit turned off + */ +static void +i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int mode = MODE_I2C_STOP; + + if (reading) + mode |= MODE_I2C_READ; + else + mode |= MODE_I2C_WRITE; + if (algo_data->running) { + (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); + algo_data->running = false; + } +} + +/* + * Write a single byte to the current I2C address, the + * the I2C link must be running or this returns -EIO + */ +static int +i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int ret; + + if (!algo_data->running) + return -EIO; + + ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); + return ret; +} + +/* + * Read a single byte from the current I2C address, the + * I2C link must be running or this returns -EIO + */ +static int +i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int ret; + + if (!algo_data->running) + return -EIO; + + ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); + return ret; +} + +static int +i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, + int num) +{ + int ret = 0; + bool reading = false; + int m; + int b; + + for (m = 0; m < num; m++) { + u16 len = msgs[m].len; + u8 *buf = msgs[m].buf; + reading = (msgs[m].flags & I2C_M_RD) != 0; + ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); + if (ret < 0) + break; + if (reading) { + for (b = 0; b < len; b++) { + ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); + if (ret < 0) + break; + } + } else { + for (b = 0; b < len; b++) { + ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); + if (ret < 0) + break; + } + } + if (ret < 0) + break; + } + if (ret >= 0) + ret = num; + i2c_algo_dp_aux_stop(adapter, reading); + printk(KERN_ERR "dp_aux_xfer return %d\n", ret); + return ret; +} + +static u32 +i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | + I2C_FUNC_10BIT_ADDR; +} + +static const struct i2c_algorithm i2c_dp_aux_algo = { + .master_xfer = i2c_algo_dp_aux_xfer, + .functionality = i2c_algo_dp_aux_functionality, +}; + +static void +i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) +{ + (void) i2c_algo_dp_aux_address(adapter, 0, false); + (void) i2c_algo_dp_aux_stop(adapter, false); + +} + +static int +i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) +{ + adapter->algo = &i2c_dp_aux_algo; + adapter->retries = 3; + i2c_dp_aux_reset_bus(adapter); + return 0; +} + +int +i2c_dp_aux_add_bus(struct i2c_adapter *adapter) +{ + int error; + + error = i2c_dp_aux_prepare_bus(adapter); + if (error) + return error; + error = i2c_add_adapter(adapter); + return error; +} +EXPORT_SYMBOL(i2c_dp_aux_add_bus); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c5858792c8063..004541c935a80 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -54,6 +54,7 @@ #define INTEL_OUTPUT_LVDS 4 #define INTEL_OUTPUT_TVOUT 5 #define INTEL_OUTPUT_HDMI 6 +#define INTEL_OUTPUT_DISPLAYPORT 7 #define INTEL_DVO_CHIP_NONE 0 #define INTEL_DVO_CHIP_LVDS 1 @@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); extern void intel_dvo_init(struct drm_device *dev); extern void intel_tv_init(struct drm_device *dev); extern void intel_lvds_init(struct drm_device *dev); +extern void intel_dp_init(struct drm_device *dev, int dp_reg); +void +intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_encoder_prepare (struct drm_encoder *encoder); -- GitLab From c8110e52b753f3d105604df84ac06cd6d1645409 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 6 May 2009 11:51:10 -0700 Subject: [PATCH 0017/1002] drm/i915: Use hotplug callback to retrain DP link When a DP monitor is plugged back in, it needs to be retrained if it was active before. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_dp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c57cdab4f4a6f..3f8d7b449e70f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -47,6 +47,7 @@ struct intel_dp_priv { uint32_t save_DP; uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE]; bool has_audio; + int dpms_mode; uint8_t link_bw; uint8_t lane_count; uint8_t dpcd[4]; @@ -527,6 +528,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) if (!(dp_reg & DP_PORT_EN)) intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); } + dp_priv->dpms_mode = mode; } /* @@ -902,7 +904,6 @@ intel_dp_restore(struct drm_connector *connector) intel_dp_link_down(intel_output, dp_priv->save_DP); } -#if 0 /* * According to DP spec * 5.1.2: @@ -929,7 +930,6 @@ intel_dp_check_link_status(struct intel_output *intel_output) if (!intel_channel_eq_ok(link_status, dp_priv->lane_count)) intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); } -#endif /** * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. @@ -1043,6 +1043,15 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = { .destroy = intel_dp_enc_destroy, }; +void +intel_dp_hot_plug(struct intel_output *intel_output) +{ + struct intel_dp_priv *dp_priv = intel_output->dev_priv; + + if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) + intel_dp_check_link_status(intel_output); +} + void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1071,6 +1080,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) dp_priv->intel_output = intel_output; dp_priv->output_reg = output_reg; dp_priv->has_audio = false; + dp_priv->dpms_mode = DRM_MODE_DPMS_ON; intel_output->dev_priv = dp_priv; drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs, @@ -1086,6 +1096,7 @@ intel_dp_init(struct drm_device *dev, int output_reg) (output_reg == DP_B) ? "DPDDC-B" : (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); intel_output->ddc_bus = &dp_priv->adapter; + intel_output->hot_plug = intel_dp_hot_plug; /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written * 0xd. Failure to do so will result in spurious interrupts being -- GitLab From e4b366996bc58a02b9dc35db3ef83f0454553f50 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Fri, 5 Jun 2009 19:22:17 -0700 Subject: [PATCH 0018/1002] drm/i915: Split array of DAC limits into separate structures. The array of DAC limits was only ever referenced with #defined constant offsets, and keeping those #define values in sync with the array itself was a nuisance. This will make future changes to the set of DAC limits less error-prone. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_display.c | 108 +++++++++++++-------------- 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5af55aa0d7a65..73e7b9cecac82 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -128,20 +128,6 @@ struct intel_limit { #define I9XX_P2_LVDS_FAST 7 #define I9XX_P2_LVDS_SLOW_LIMIT 112000 -#define INTEL_LIMIT_I8XX_DVO_DAC 0 -#define INTEL_LIMIT_I8XX_LVDS 1 -#define INTEL_LIMIT_I9XX_SDVO_DAC 2 -#define INTEL_LIMIT_I9XX_LVDS 3 -#define INTEL_LIMIT_G4X_SDVO 4 -#define INTEL_LIMIT_G4X_HDMI_DAC 5 -#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 -#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 -#define INTEL_LIMIT_G4X_DISPLAY_PORT 8 -#define INTEL_LIMIT_IGD_SDVO_DAC 9 -#define INTEL_LIMIT_IGD_LVDS 10 -#define INTEL_LIMIT_IGDNG_SDVO_DAC 11 -#define INTEL_LIMIT_IGDNG_LVDS 12 - /*The parameter is for SDVO on G4x platform*/ #define G4X_DOT_SDVO_MIN 25000 #define G4X_DOT_SDVO_MAX 270000 @@ -281,8 +267,7 @@ static bool intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); -static const intel_limit_t intel_limits[] = { - { /* INTEL_LIMIT_I8XX_DVO_DAC */ +static const intel_limit_t intel_limits_i8xx_dvo = { .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, @@ -294,8 +279,9 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, .find_pll = intel_find_best_PLL, - }, - { /* INTEL_LIMIT_I8XX_LVDS */ +}; + +static const intel_limit_t intel_limits_i8xx_lvds = { .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, @@ -307,8 +293,9 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - }, - { /* INTEL_LIMIT_I9XX_SDVO_DAC */ +}; + +static const intel_limit_t intel_limits_i9xx_sdvo = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, @@ -320,8 +307,9 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - }, - { /* INTEL_LIMIT_I9XX_LVDS */ +}; + +static const intel_limit_t intel_limits_i9xx_lvds = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, @@ -336,9 +324,10 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - }, +}; + /* below parameter and function is for G4X Chipset Family*/ - { /* INTEL_LIMIT_G4X_SDVO */ +static const intel_limit_t intel_limits_g4x_sdvo = { .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, @@ -352,8 +341,9 @@ static const intel_limit_t intel_limits[] = { .p2_fast = G4X_P2_SDVO_FAST }, .find_pll = intel_g4x_find_best_PLL, - }, - { /* INTEL_LIMIT_G4X_HDMI_DAC */ +}; + +static const intel_limit_t intel_limits_g4x_hdmi = { .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, @@ -367,8 +357,9 @@ static const intel_limit_t intel_limits[] = { .p2_fast = G4X_P2_HDMI_DAC_FAST }, .find_pll = intel_g4x_find_best_PLL, - }, - { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ +}; + +static const intel_limit_t intel_limits_g4x_single_channel_lvds = { .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, .vco = { .min = G4X_VCO_MIN, @@ -390,8 +381,9 @@ static const intel_limit_t intel_limits[] = { .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - }, - { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ +}; + +static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, .vco = { .min = G4X_VCO_MIN, @@ -413,8 +405,9 @@ static const intel_limit_t intel_limits[] = { .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - }, - { /* INTEL_LIMIT_G4X_DISPLAY_PORT */ +}; + +static const intel_limit_t intel_limits_g4x_display_port = { .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, .max = G4X_DOT_DISPLAY_PORT_MAX }, .vco = { .min = G4X_VCO_MIN, @@ -435,8 +428,9 @@ static const intel_limit_t intel_limits[] = { .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, .find_pll = intel_find_pll_g4x_dp, - }, - { /* INTEL_LIMIT_IGD_SDVO */ +}; + +static const intel_limit_t intel_limits_igd_sdvo = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, @@ -448,8 +442,9 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - }, - { /* INTEL_LIMIT_IGD_LVDS */ +}; + +static const intel_limit_t intel_limits_igd_lvds = { .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, @@ -462,8 +457,9 @@ static const intel_limit_t intel_limits[] = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, .find_pll = intel_find_best_PLL, - }, - { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ +}; + +static const intel_limit_t intel_limits_igdng_sdvo = { .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, @@ -476,8 +472,9 @@ static const intel_limit_t intel_limits[] = { .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, .find_pll = intel_igdng_find_best_PLL, - }, - { /* INTEL_LIMIT_IGDNG_LVDS */ +}; + +static const intel_limit_t intel_limits_igdng_lvds = { .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, @@ -490,16 +487,15 @@ static const intel_limit_t intel_limits[] = { .p2_slow = IGDNG_P2_LVDS_SLOW, .p2_fast = IGDNG_P2_LVDS_FAST }, .find_pll = intel_igdng_find_best_PLL, - }, }; static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) { const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; + limit = &intel_limits_igdng_lvds; else - limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; + limit = &intel_limits_igdng_sdvo; return limit; } @@ -514,21 +510,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) /* LVDS with dual channel */ - limit = &intel_limits - [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; + limit = &intel_limits_g4x_dual_channel_lvds; else /* LVDS with dual channel */ - limit = &intel_limits - [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; + limit = &intel_limits_g4x_single_channel_lvds; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { - limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; + limit = &intel_limits_g4x_hdmi; } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { - limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; + limit = &intel_limits_g4x_sdvo; } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { - limit = &intel_limits[INTEL_LIMIT_G4X_DISPLAY_PORT]; + limit = &intel_limits_g4x_display_port; } else /* The option is for other outputs */ - limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + limit = &intel_limits_i9xx_sdvo; return limit; } @@ -544,19 +538,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) limit = intel_g4x_limit(crtc); } else if (IS_I9XX(dev) && !IS_IGD(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; + limit = &intel_limits_i9xx_lvds; else - limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; + limit = &intel_limits_i9xx_sdvo; } else if (IS_IGD(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; + limit = &intel_limits_igd_lvds; else - limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; + limit = &intel_limits_igd_sdvo; } else { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; + limit = &intel_limits_i8xx_lvds; else - limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; + limit = &intel_limits_i8xx_dvo; } return limit; } -- GitLab From b11248df4c0decb1e473d5025f237be32c0f67bb Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Thu, 11 Jun 2009 22:28:56 -0700 Subject: [PATCH 0019/1002] drm/i915: Add CLKCFG register definition The CLKCFG register holds information about the GMCH plls and input clock values. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/i915_reg.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f6237a0b1133c..544d5677a2fa2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -569,6 +569,19 @@ #define C0DRB3 0x10206 #define C1DRB3 0x10606 +/* Clocking configuration register */ +#define CLKCFG 0x10c00 +#define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ +#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ +#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ +#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ +#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ +#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ +/* this is a guess, could be 5 as well */ +#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_MASK (7 << 0) + /** GM965 GM45 render standby register */ #define MCHBAR_RENDER_STANDBY 0x111B8 -- GitLab From a5b3da543d4882d57a2f3e05d37ad8e1e1453489 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Thu, 11 Jun 2009 22:30:32 -0700 Subject: [PATCH 0020/1002] drm/i915: Clarify error returns from display port aux channel I/O Use distinct error return values for each kind of aux channel I/O failure. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_dp.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3f8d7b449e70f..818fe34f2b5ce 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -209,15 +209,19 @@ intel_dp_aux_ch(struct intel_output *intel_output, if ((status & DP_AUX_CH_CTL_DONE) == 0) { printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); - return -1; + return -EBUSY; } /* Check for timeout or receive error. * Timeouts occur when the sink is not connected */ - if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_RECEIVE_ERROR)) { - printk(KERN_ERR "dp_aux_ch error status 0x%08x\n", status); - return -1; + if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { + printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status); + return -EIO; + } + if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { + printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status); + return -ETIMEDOUT; } /* Unload any bytes sent back from the other side */ @@ -263,7 +267,7 @@ intel_dp_aux_native_write(struct intel_output *intel_output, else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) udelay(100); else - return -1; + return -EIO; } return send_bytes; } @@ -299,7 +303,9 @@ intel_dp_aux_native_read(struct intel_output *intel_output, for (;;) { ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, reply, reply_bytes); - if (ret <= 0) + if (ret == 0) + return -EPROTO; + if (ret < 0) return ret; ack = reply[0]; if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { @@ -309,7 +315,7 @@ intel_dp_aux_native_read(struct intel_output *intel_output, else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) udelay(100); else - return -1; + return -EIO; } } -- GitLab From fb0f8fbf97e8a25074c81c629500d94cafa9e366 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Thu, 11 Jun 2009 22:31:31 -0700 Subject: [PATCH 0021/1002] drm/i915: Generate 2MHz clock for display port aux channel I/O. Retry I/O. The display port aux channel clock is taken from the hrawclk value, which is provided to the chip as the FSB frequency (as far as I can determine). The strapping values for that are available in the CLKCFG register, now used to select an appropriate divider to generate a 2MHz clock. In addition, the DisplayPort spec requires that each aux channel I/O be retried 'at least 3 times' in case the sink is idle when the first request comes in. Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/intel_dp.c | 102 ++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 818fe34f2b5ce..8f8d37d5663a0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -154,6 +154,36 @@ unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) dst[i] = src >> ((3-i) * 8); } +/* hrawclock is 1/4 the FSB frequency */ +static int +intel_hrawclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t clkcfg; + + clkcfg = I915_READ(CLKCFG); + switch (clkcfg & CLKCFG_FSB_MASK) { + case CLKCFG_FSB_400: + return 100; + case CLKCFG_FSB_533: + return 133; + case CLKCFG_FSB_667: + return 166; + case CLKCFG_FSB_800: + return 200; + case CLKCFG_FSB_1067: + return 266; + case CLKCFG_FSB_1333: + return 333; + /* these two are just a guess; one of them might be right */ + case CLKCFG_FSB_1600: + case CLKCFG_FSB_1600_ALT: + return 400; + default: + return 133; + } +} + static int intel_dp_aux_ch(struct intel_output *intel_output, uint8_t *send, int send_bytes, @@ -169,44 +199,52 @@ intel_dp_aux_ch(struct intel_output *intel_output, int recv_bytes; uint32_t ctl; uint32_t status; - - /* Load the send data into the aux channel data registers */ - for (i = 0; i < send_bytes; i += 4) { - uint32_t d = pack_aux(send + i, send_bytes - i);; - - I915_WRITE(ch_data + i, d); - } + uint32_t aux_clock_divider; + int try; /* The clock divider is based off the hrawclk, - * and would like to run at 2MHz. The 133 below assumes - * a 266MHz hrawclk; need to figure out how we're supposed - * to know what hrawclk is... + * and would like to run at 2MHz. So, take the + * hrawclk value and divide by 2 and use that */ - ctl = (DP_AUX_CH_CTL_SEND_BUSY | - DP_AUX_CH_CTL_TIME_OUT_1600us | - (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | - (133 << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); - - /* Send the command and wait for it to complete */ - I915_WRITE(ch_ctl, ctl); - (void) I915_READ(ch_ctl); - for (;;) { - udelay(100); - status = I915_READ(ch_ctl); - if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + aux_clock_divider = intel_hrawclk(dev) / 2; + /* Must try at least 3 times according to DP spec */ + for (try = 0; try < 5; try++) { + /* Load the send data into the aux channel data registers */ + for (i = 0; i < send_bytes; i += 4) { + uint32_t d = pack_aux(send + i, send_bytes - i);; + + I915_WRITE(ch_data + i, d); + } + + ctl = (DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + + /* Send the command and wait for it to complete */ + I915_WRITE(ch_ctl, ctl); + (void) I915_READ(ch_ctl); + for (;;) { + udelay(100); + status = I915_READ(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + } + + /* Clear done status and any errors */ + I915_WRITE(ch_ctl, (ctl | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR)); + (void) I915_READ(ch_ctl); + if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) break; } - /* Clear done status and any errors */ - I915_WRITE(ch_ctl, (ctl | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR)); - (void) I915_READ(ch_ctl); - if ((status & DP_AUX_CH_CTL_DONE) == 0) { printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); return -EBUSY; -- GitLab From 99bd0c0fc4b04da54cb311953ef9489931c19c63 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann <andreas.herrmann3@amd.com> Date: Fri, 19 Jun 2009 10:59:09 +0200 Subject: [PATCH 0022/1002] x86: Set cpu_llc_id on AMD CPUs This counts when building sched domains in case NUMA information is not available. ( See cpu_coregroup_mask() which uses llc_shared_map which in turn is created based on cpu_llc_id. ) Currently Linux builds domains as follows: (example from a dual socket quad-core system) CPU0 attaching sched-domain: domain 0: span 0-7 level CPU groups: 0 1 2 3 4 5 6 7 ... CPU7 attaching sched-domain: domain 0: span 0-7 level CPU groups: 7 0 1 2 3 4 5 6 Ever since that is borked for multi-core AMD CPU systems. This patch fixes that and now we get a proper: CPU0 attaching sched-domain: domain 0: span 0-3 level MC groups: 0 1 2 3 domain 1: span 0-7 level CPU groups: 0-3 4-7 ... CPU7 attaching sched-domain: domain 0: span 4-7 level MC groups: 7 4 5 6 domain 1: span 0-7 level CPU groups: 4-7 0-3 This allows scheduler to assign tasks to cores on different sockets (i.e. that don't share last level cache) for performance reasons. Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com> LKML-Reference: <20090619085909.GJ5218@alberich.amd.com> Cc: <stable@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/cpu/amd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e5b27d8f1b473..28e5f59560429 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -258,13 +258,15 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT unsigned bits; + int cpu = smp_processor_id(); bits = c->x86_coreid_bits; - /* Low order bits define the core id (index of core in socket) */ c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); /* Convert the initial APIC ID into the socket ID */ c->phys_proc_id = c->initial_apicid >> bits; + /* use socket ID also for last level cache */ + per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; #endif } -- GitLab From d9f2a5ecb2846d0fd368fb4c45182e43f38e4471 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Sat, 20 Jun 2009 13:19:25 +0530 Subject: [PATCH 0023/1002] perf_counter, x8: Fix L1-data-Cache-Store-Referencees for AMD Fix AMD's Data Cache Refills from System event. After this patch : ./tools/perf/perf stat -e l1d -e l1d-misses -e l1d-write -e l1d-prefetch -e l1d-prefetch-miss -e l1i -e l1i-misses -e l1i-prefetch -e l2 -e l2-misses -e l2-write -e dtlb -e dtlb-misses -e itlb -e itlb-misses -e bpu -e bpu-misses ls /dev/ > /dev/null Performance counter stats for 'ls /dev/': 2499484 L1-data-Cache-Load-Referencees (scaled from 3.97%) 70347 L1-data-Cache-Load-Misses (scaled from 7.30%) 9360 L1-data-Cache-Store-Referencees (scaled from 8.64%) 32804 L1-data-Cache-Prefetch-Referencees (scaled from 17.72%) 7693 L1-data-Cache-Prefetch-Misses (scaled from 22.97%) 2180945 L1-instruction-Cache-Load-Referencees (scaled from 28.48%) 14518 L1-instruction-Cache-Load-Misses (scaled from 35.00%) 2405 L1-instruction-Cache-Prefetch-Referencees (scaled from 34.89%) 71387 L2-Cache-Load-Referencees (scaled from 34.94%) 18732 L2-Cache-Load-Misses (scaled from 34.92%) 79918 L2-Cache-Store-Referencees (scaled from 36.02%) 1295294 Data-TLB-Cache-Load-Referencees (scaled from 35.99%) 30896 Data-TLB-Cache-Load-Misses (scaled from 33.36%) 1222030 Instruction-TLB-Cache-Load-Referencees (scaled from 29.46%) 357 Instruction-TLB-Cache-Load-Misses (scaled from 20.46%) 530888 Branch-Cache-Load-Referencees (scaled from 11.48%) 8638 Branch-Cache-Load-Misses (scaled from 5.09%) 0.011295149 seconds time elapsed. Earlier it always shows value 0. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> LKML-Reference: <1245484165.3102.6.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/cpu/perf_counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 76dfef23f7895..22eb3a1d4f9cd 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -401,7 +401,7 @@ static const u64 amd_hw_cache_event_ids [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ }, [ C(OP_WRITE) ] = { - [ C(RESULT_ACCESS) ] = 0x0042, /* Data Cache Refills from L2 */ + [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ [ C(RESULT_MISS) ] = 0, }, [ C(OP_PREFETCH) ] = { -- GitLab From c1f47b454ce759d7b13604137a233cad4617e1e8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Sun, 21 Jun 2009 13:58:51 +0200 Subject: [PATCH 0024/1002] perf_counter tools: Fix vmlinux fallback when running on a different kernel Lucas De Marchi reported that perf report and perf annotate displays mismatching profile if a perf.data is analyzed on an older kernel - even if the correct vmlinux is specified via the -k option. The reason is the fallback path in util/symbol.c:dso__load_kernel(): int dso__load_kernel(struct dso *self, const char *vmlinux, symbol_filter_t filter, int verbose) { int err = -1; if (vmlinux) err = dso__load_vmlinux(self, vmlinux, filter, verbose); if (err) err = dso__load_kallsyms(self, filter, verbose); return err; } dso__load_vmlinux() returns negative on error, but on success it returns the number of symbols loaded - which confuses the function to load the kallsyms. This is normally harmless, as reporting is usually performed on the same kernel that is analyzed - but if there's a mismatch then we load the wrong kallsyms and create a non-sensical symbol tree. The fix is to only fall back to kallsyms on errors. Reported-by: Lucas De Marchi <lucas.de.marchi@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/symbol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 86e14375e74e3..01b62fa039964 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -629,7 +629,7 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, if (vmlinux) err = dso__load_vmlinux(self, vmlinux, filter, verbose); - if (err) + if (err < 0) err = dso__load_kallsyms(self, filter, verbose); return err; -- GitLab From b76a3f93d01fc93a87cb6eba4e854ffe378b4bac Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Mon, 8 Jun 2009 19:28:41 +0300 Subject: [PATCH 0025/1002] exofs: Fix bio leak in error handling path (sync read) When failing a read request in the sync path, called from write_begin, I forgot to free the allocated bio, fix it. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- fs/exofs/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 77d0a295eb1cd..bb5d6ed0f7a85 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -295,6 +295,9 @@ static int read_exec(struct page_collect *pcol, bool is_sync) err: if (!is_sync) _unlock_pcol_pages(pcol, ret, READ); + else /* Pages unlocked by caller in sync mode only free bio */ + pcol_free(pcol); + kfree(pcol_copy); if (or) osd_end_request(or); -- GitLab From 27d2e1491985e95c486d991302e399f5c584b4eb Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Sun, 14 Jun 2009 17:23:09 +0300 Subject: [PATCH 0026/1002] exofs: Remove IBM copyrights Boaz, Congrats on getting all the OSD stuff into 2.6.30! I just pulled the git, and saw that the IBM copyrights are still there. Please remove them from all files: * Copyright (C) 2005, 2006 * International Business Machines IBM has revoked all rights on the code - they gave it to me. Thanks! Avishay Signed-off-by: Avishay Traeger <avishay@gmail.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- fs/exofs/common.h | 4 +--- fs/exofs/dir.c | 4 +--- fs/exofs/exofs.h | 4 +--- fs/exofs/file.c | 4 +--- fs/exofs/inode.c | 4 +--- fs/exofs/namei.c | 4 +--- fs/exofs/osd.c | 4 +--- fs/exofs/super.c | 4 +--- fs/exofs/symlink.c | 4 +--- 9 files changed, 9 insertions(+), 27 deletions(-) diff --git a/fs/exofs/common.h b/fs/exofs/common.h index 24667eedc0232..c6718e4817fea 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h @@ -2,9 +2,7 @@ * common.h - Common definitions for both Kernel and user-mode utilities * * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index 65b0c8c776a1d..4cfab1cc75c03 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 0fd4c78596793..c413b74ecf310 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/file.c b/fs/exofs/file.c index 6ed7fe4847522..c6810038d6377 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index bb5d6ed0f7a85..6c10f7476699c 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c index 77fdd765e76d1..b7dd0c2368637 100644 --- a/fs/exofs/namei.c +++ b/fs/exofs/namei.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/osd.c b/fs/exofs/osd.c index b3d2ccb87aaa8..4372542df284e 100644 --- a/fs/exofs/osd.c +++ b/fs/exofs/osd.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 8216c5b77b532..e47b38e55a262 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * diff --git a/fs/exofs/symlink.c b/fs/exofs/symlink.c index 36e2d7bc7f7bd..4dd687c3e7474 100644 --- a/fs/exofs/symlink.c +++ b/fs/exofs/symlink.c @@ -1,8 +1,6 @@ /* * Copyright (C) 2005, 2006 - * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) - * Copyright (C) 2005, 2006 - * International Business Machines + * Avishay Traeger (avishay@gmail.com) * Copyright (C) 2008, 2009 * Boaz Harrosh <bharrosh@panasas.com> * -- GitLab From baaf94cdc7fe1c61e3c660a3b055724fd9d0a034 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Sun, 14 Jun 2009 16:52:10 +0300 Subject: [PATCH 0027/1002] exofs: Avoid using file_fsync() The use of file_fsync() in exofs_file_sync() is not necessary since it does some extra stuff not used by exofs. Open code just the parts that are currently needed. TODO: Farther optimization can be done to sync the sb only on inode update of new files, Usually the sb update is not needed in exofs. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- fs/exofs/exofs.h | 3 +++ fs/exofs/file.c | 17 ++++++++++++----- fs/exofs/super.c | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index c413b74ecf310..5ec72e020b22b 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -154,6 +154,9 @@ ino_t exofs_parent_ino(struct dentry *child); int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, struct inode *); +/* super.c */ +int exofs_sync_fs(struct super_block *sb, int wait); + /********************* * operation vectors * *********************/ diff --git a/fs/exofs/file.c b/fs/exofs/file.c index c6810038d6377..839b9dc1e70f3 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -45,16 +45,23 @@ static int exofs_file_fsync(struct file *filp, struct dentry *dentry, { int ret; struct address_space *mapping = filp->f_mapping; + struct inode *inode = dentry->d_inode; + struct super_block *sb; ret = filemap_write_and_wait(mapping); if (ret) return ret; - /*Note: file_fsync below also calles sync_blockdev, which is a no-op - * for exofs, but other then that it does sync_inode and - * sync_superblock which is what we need here. - */ - return file_fsync(filp, dentry, datasync); + /* sync the inode attributes */ + ret = write_inode_now(inode, 1); + + /* This is a good place to write the sb */ + /* TODO: Sechedule an sb-sync on create */ + sb = inode->i_sb; + if (sb->s_dirt) + exofs_sync_fs(sb, 1); + + return ret; } static int exofs_flush(struct file *file, fl_owner_t id) diff --git a/fs/exofs/super.c b/fs/exofs/super.c index e47b38e55a262..a343b4ea62f61 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -198,7 +198,7 @@ static const struct export_operations exofs_export_ops; /* * Write the superblock to the OSD */ -static int exofs_sync_fs(struct super_block *sb, int wait) +int exofs_sync_fs(struct super_block *sb, int wait) { struct exofs_sb_info *sbi; struct exofs_fscb *fscb; -- GitLab From 42c55aa838bbd274a7ad2be1fd81d423ca63da4e Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Wed, 17 Jun 2009 16:54:34 +0300 Subject: [PATCH 0028/1002] MAINTAINERS: Add osd maintained files (F:) OSD files are found in three places: drivers/scsi/osd/ include/scsi/osd_* fs/exofs/ Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- MAINTAINERS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index dc226e78612c7..b9b208955098a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4321,7 +4321,7 @@ W: http://www.nongnu.org/orinoco/ S: Maintained F: drivers/net/wireless/orinoco/ -OSD LIBRARY +OSD LIBRARY and FILESYSTEM P: Boaz Harrosh M: bharrosh@panasas.com P: Benny Halevy @@ -4330,6 +4330,9 @@ L: osd-dev@open-osd.org W: http://open-osd.org T: git git://git.open-osd.org/open-osd.git S: Maintained +F: drivers/scsi/osd/ +F: drivers/include/scsi/osd_* +F: fs/exofs/ P54 WIRELESS DRIVER P: Michael Wu -- GitLab From 85ae87c1ad8e18a421e7448a99a42ecda183f29f Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:23 +0900 Subject: [PATCH 0029/1002] percpu: fix too lazy vunmap cache flushing In pcpu_unmap(), flushing virtual cache on vunmap can't be delayed as the page is going to be returned to the page allocator. Only TLB flushing can be put off such that vmalloc code can handle it lazily. Fix it. [ Impact: fix subtle virtual cache flush bug ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Nick Piggin <npiggin@suse.de> Cc: Ingo Molnar <mingo@elte.hu> --- mm/percpu.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mm/percpu.c b/mm/percpu.c index c0b2c1a76e81c..d06f4748271e4 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -549,14 +549,14 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) * @chunk: chunk of interest * @page_start: page index of the first page to unmap * @page_end: page index of the last page to unmap + 1 - * @flush: whether to flush cache and tlb or not + * @flush_tlb: whether to flush tlb or not * * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. * If @flush is true, vcache is flushed before unmapping and tlb * after. */ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, - bool flush) + bool flush_tlb) { unsigned int last = num_possible_cpus() - 1; unsigned int cpu; @@ -569,9 +569,8 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, * the whole region at once rather than doing it for each cpu. * This could be an overkill but is more scalable. */ - if (flush) - flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), - pcpu_chunk_addr(chunk, last, page_end)); + flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), + pcpu_chunk_addr(chunk, last, page_end)); for_each_possible_cpu(cpu) unmap_kernel_range_noflush( @@ -579,7 +578,7 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, (page_end - page_start) << PAGE_SHIFT); /* ditto as flush_cache_vunmap() */ - if (flush) + if (flush_tlb) flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), pcpu_chunk_addr(chunk, last, page_end)); } -- GitLab From c5806df9232d2a7f554b4839b57cac2e664fc256 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0030/1002] x86: fix duplicate free in setup_pcpu_remap() failure path In the failure path, setup_pcpu_remap() tries to free the area which has already been freed to make holes in the large page. Fix it. [ Impact: fix duplicate free in failure path ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/setup_percpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 9c3f0823e6aa0..dfbc7e6c64d40 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -228,7 +228,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) enomem: for_each_possible_cpu(cpu) if (pcpur_ptrs[cpu]) - free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE); + free_bootmem(__pa(pcpur_ptrs[cpu]), pcpur_size); ret = -ENOMEM; out_free_ar: free_bootmem(__pa(pcpur_ptrs), ptrs_size); -- GitLab From 97c9bf0618cd40b05b4859c1f8a90d8ad97fefb2 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0031/1002] x86: rename remap percpu first chunk allocator to lpage The "remap" allocator remaps large pages to build the first chunk; however, the name isn't very good because 4k allocator remaps too and the whole point of the remap allocator is using large page mapping. The allocator will be generalized and exported outside of x86, rename it to lpage before that happens. percpu_alloc kernel parameter is updated to accept both "remap" and "lpage" for lpage allocator. [ Impact: code cleanup, kernel parameter argument updated ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/setup_percpu.c | 50 +++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index dfbc7e6c64d40..8794c0c94d2ce 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -124,7 +124,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, } /* - * Remap allocator + * Large page remap allocator * * This allocator uses PMD page as unit. A PMD page is allocated for * each cpu and each is remapped into vmalloc area using PMD mapping. @@ -137,20 +137,20 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, * better than only using 4k mappings while still being NUMA friendly. */ #ifdef CONFIG_NEED_MULTIPLE_NODES -static size_t pcpur_size __initdata; -static void **pcpur_ptrs __initdata; +static size_t pcpul_size __initdata; +static void **pcpul_ptrs __initdata; -static struct page * __init pcpur_get_page(unsigned int cpu, int pageno) +static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) { size_t off = (size_t)pageno << PAGE_SHIFT; - if (off >= pcpur_size) + if (off >= pcpul_size) return NULL; - return virt_to_page(pcpur_ptrs[cpu] + off); + return virt_to_page(pcpul_ptrs[cpu] + off); } -static ssize_t __init setup_pcpu_remap(size_t static_size) +static ssize_t __init setup_pcpu_lpage(size_t static_size) { static struct vm_struct vm; size_t ptrs_size, dyn_size; @@ -170,36 +170,36 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * Currently supports only single page. Supporting multiple * pages won't be too difficult if it ever becomes necessary. */ - pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + + pcpul_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE); - if (pcpur_size > PMD_SIZE) { + if (pcpul_size > PMD_SIZE) { pr_warning("PERCPU: static data is larger than large page, " "can't use large page\n"); return -EINVAL; } - dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; + dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; /* allocate pointer array and alloc large pages */ - ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); - pcpur_ptrs = alloc_bootmem(ptrs_size); + ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpul_ptrs[0])); + pcpul_ptrs = alloc_bootmem(ptrs_size); for_each_possible_cpu(cpu) { - pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); - if (!pcpur_ptrs[cpu]) + pcpul_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); + if (!pcpul_ptrs[cpu]) goto enomem; /* - * Only use pcpur_size bytes and give back the rest. + * Only use pcpul_size bytes and give back the rest. * * Ingo: The 2MB up-rounding bootmem is needed to make * sure the partial 2MB page is still fully RAM - it's * not well-specified to have a PAT-incompatible area * (unmapped RAM, device memory, etc.) in that hole. */ - free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size), - PMD_SIZE - pcpur_size); + free_bootmem(__pa(pcpul_ptrs[cpu] + pcpul_size), + PMD_SIZE - pcpul_size); - memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size); + memcpy(pcpul_ptrs[cpu], __per_cpu_load, static_size); } /* allocate address and map */ @@ -212,7 +212,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) pmd = populate_extra_pmd((unsigned long)vm.addr + cpu * PMD_SIZE); - set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])), + set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpul_ptrs[cpu])), PAGE_KERNEL_LARGE)); } @@ -220,22 +220,22 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) pr_info("PERCPU: Remapped at %p with large pages, static data " "%zu bytes\n", vm.addr, static_size); - ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, + ret = pcpu_setup_first_chunk(pcpul_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, dyn_size, PMD_SIZE, vm.addr, NULL); goto out_free_ar; enomem: for_each_possible_cpu(cpu) - if (pcpur_ptrs[cpu]) - free_bootmem(__pa(pcpur_ptrs[cpu]), pcpur_size); + if (pcpul_ptrs[cpu]) + free_bootmem(__pa(pcpul_ptrs[cpu]), pcpul_size); ret = -ENOMEM; out_free_ar: - free_bootmem(__pa(pcpur_ptrs), ptrs_size); + free_bootmem(__pa(pcpul_ptrs), ptrs_size); return ret; } #else -static ssize_t __init setup_pcpu_remap(size_t static_size) +static ssize_t __init setup_pcpu_lpage(size_t static_size) { return -EINVAL; } @@ -367,7 +367,7 @@ void __init setup_per_cpu_areas(void) * of large page mappings. Please read comments on top of * each allocator for details. */ - ret = setup_pcpu_remap(static_size); + ret = setup_pcpu_lpage(static_size); if (ret < 0) ret = setup_pcpu_embed(static_size); if (ret < 0) -- GitLab From 0ff2587fd54bd6f66bc6914ada4eb77a7e819a5b Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0032/1002] x86: prepare setup_pcpu_lpage() for pageattr fix Make the following changes in preparation of coming pageattr updates. * Define and use array of struct pcpul_ent instead of array of pointers. The only difference is ->cpu field which is set but unused yet. * Rename variables according to the above change. * Rename local variable vm to pcpul_vm and move it out of the function. [ Impact: no functional difference ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Jan Beulich <JBeulich@novell.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/setup_percpu.c | 58 +++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 8794c0c94d2ce..7d38941e2b8c5 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -137,8 +137,14 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, * better than only using 4k mappings while still being NUMA friendly. */ #ifdef CONFIG_NEED_MULTIPLE_NODES +struct pcpul_ent { + unsigned int cpu; + void *ptr; +}; + static size_t pcpul_size __initdata; -static void **pcpul_ptrs __initdata; +static struct pcpul_ent *pcpul_map __initdata; +static struct vm_struct pcpul_vm; static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) { @@ -147,13 +153,12 @@ static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) if (off >= pcpul_size) return NULL; - return virt_to_page(pcpul_ptrs[cpu] + off); + return virt_to_page(pcpul_map[cpu].ptr + off); } static ssize_t __init setup_pcpu_lpage(size_t static_size) { - static struct vm_struct vm; - size_t ptrs_size, dyn_size; + size_t map_size, dyn_size; unsigned int cpu; ssize_t ret; @@ -180,12 +185,14 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; /* allocate pointer array and alloc large pages */ - ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpul_ptrs[0])); - pcpul_ptrs = alloc_bootmem(ptrs_size); + map_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpul_map[0])); + pcpul_map = alloc_bootmem(map_size); for_each_possible_cpu(cpu) { - pcpul_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); - if (!pcpul_ptrs[cpu]) + pcpul_map[cpu].cpu = cpu; + pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE, + PMD_SIZE); + if (!pcpul_map[cpu].ptr) goto enomem; /* @@ -196,42 +203,43 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) * not well-specified to have a PAT-incompatible area * (unmapped RAM, device memory, etc.) in that hole. */ - free_bootmem(__pa(pcpul_ptrs[cpu] + pcpul_size), + free_bootmem(__pa(pcpul_map[cpu].ptr + pcpul_size), PMD_SIZE - pcpul_size); - memcpy(pcpul_ptrs[cpu], __per_cpu_load, static_size); + memcpy(pcpul_map[cpu].ptr, __per_cpu_load, static_size); } /* allocate address and map */ - vm.flags = VM_ALLOC; - vm.size = num_possible_cpus() * PMD_SIZE; - vm_area_register_early(&vm, PMD_SIZE); + pcpul_vm.flags = VM_ALLOC; + pcpul_vm.size = num_possible_cpus() * PMD_SIZE; + vm_area_register_early(&pcpul_vm, PMD_SIZE); for_each_possible_cpu(cpu) { - pmd_t *pmd; + pmd_t *pmd, pmd_v; - pmd = populate_extra_pmd((unsigned long)vm.addr - + cpu * PMD_SIZE); - set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpul_ptrs[cpu])), - PAGE_KERNEL_LARGE)); + pmd = populate_extra_pmd((unsigned long)pcpul_vm.addr + + cpu * PMD_SIZE); + pmd_v = pfn_pmd(page_to_pfn(virt_to_page(pcpul_map[cpu].ptr)), + PAGE_KERNEL_LARGE); + set_pmd(pmd, pmd_v); } /* we're ready, commit */ pr_info("PERCPU: Remapped at %p with large pages, static data " - "%zu bytes\n", vm.addr, static_size); + "%zu bytes\n", pcpul_vm.addr, static_size); ret = pcpu_setup_first_chunk(pcpul_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, dyn_size, - PMD_SIZE, vm.addr, NULL); - goto out_free_ar; + PMD_SIZE, pcpul_vm.addr, NULL); + goto out_free_map; enomem: for_each_possible_cpu(cpu) - if (pcpul_ptrs[cpu]) - free_bootmem(__pa(pcpul_ptrs[cpu]), pcpul_size); + if (pcpul_map[cpu].ptr) + free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size); ret = -ENOMEM; -out_free_ar: - free_bootmem(__pa(pcpul_ptrs), ptrs_size); +out_free_map: + free_bootmem(__pa(pcpul_map), map_size); return ret; } #else -- GitLab From 992f4c1c2c1583cef3296ec4bf5205843a9a5f3d Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0033/1002] x86: reorganize cpa_process_alias() Reorganize cpa_process_alias() so that new alias condition can be added easily. Jan Beulich spotted problem in the original cleanup thread which incorrectly assumed the two existing conditions were mutially exclusive. [ Impact: code reorganization ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Jan Beulich <JBeulich@novell.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/mm/pageattr.c | 50 +++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 3cfe9ced8a4c6..2ab058b0947de 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -681,8 +681,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias); static int cpa_process_alias(struct cpa_data *cpa) { struct cpa_data alias_cpa; - int ret = 0; - unsigned long temp_cpa_vaddr, vaddr; + unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT); + unsigned long vaddr; + int ret; if (cpa->pfn >= max_pfn_mapped) return 0; @@ -706,42 +707,37 @@ static int cpa_process_alias(struct cpa_data *cpa) PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) { alias_cpa = *cpa; - temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); - alias_cpa.vaddr = &temp_cpa_vaddr; + alias_cpa.vaddr = &laddr; alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); - ret = __change_page_attr_set_clr(&alias_cpa, 0); + if (ret) + return ret; } #ifdef CONFIG_X86_64 - if (ret) - return ret; /* - * No need to redo, when the primary call touched the high - * mapping already: - */ - if (within(vaddr, (unsigned long) _text, _brk_end)) - return 0; - - /* - * If the physical address is inside the kernel map, we need + * If the primary call didn't touch the high mapping already + * and the physical address is inside the kernel map, we need * to touch the high mapped kernel as well: */ - if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) - return 0; - - alias_cpa = *cpa; - temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; - alias_cpa.vaddr = &temp_cpa_vaddr; - alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); + if (!within(vaddr, (unsigned long)_text, _brk_end) && + within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) { + unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + + __START_KERNEL_map - phys_base; + alias_cpa = *cpa; + alias_cpa.vaddr = &temp_cpa_vaddr; + alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); - /* - * The high mapping range is imprecise, so ignore the return value. - */ - __change_page_attr_set_clr(&alias_cpa, 0); + /* + * The high mapping range is imprecise, so ignore the + * return value. + */ + __change_page_attr_set_clr(&alias_cpa, 0); + } #endif - return ret; + + return 0; } static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) -- GitLab From e59a1bb2fdfb745c685f5b40ffbed126331d3223 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0034/1002] x86: fix pageattr handling for lpage percpu allocator and re-enable it lpage allocator aliases a PMD page for each cpu and returns whatever is unused to the page allocator. When the pageattr of the recycled pages are changed, this makes the two aliases point to the overlapping regions with different attributes which isn't allowed and known to cause subtle data corruption in certain cases. This can be handled in simliar manner to the x86_64 highmap alias. pageattr code should detect if the target pages have PMD alias and split the PMD alias and synchronize the attributes. pcpur allocator is updated to keep the allocated PMD pages map sorted in ascending address order and provide pcpu_lpage_remapped() function which binary searches the array to determine whether the given address is aliased and if so to which address. pageattr is updated to use pcpu_lpage_remapped() to detect the PMD alias and split it up as necessary from cpa_process_alias(). Jan Beulich spotted the original problem and incorrect usage of vaddr instead of laddr for lookup. With this, lpage percpu allocator should work correctly. Re-enable it. [ Impact: fix subtle lpage pageattr bug and re-enable lpage ] Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Jan Beulich <JBeulich@novell.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/percpu.h | 10 +++++ arch/x86/kernel/setup_percpu.c | 72 +++++++++++++++++++++++++++++----- arch/x86/mm/pageattr.c | 21 +++++++++- 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 02ecb30982a3a..103f1ddb0d85b 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -42,6 +42,7 @@ #else /* ...!ASSEMBLY */ +#include <linux/kernel.h> #include <linux/stringify.h> #ifdef CONFIG_SMP @@ -155,6 +156,15 @@ do { \ /* We can use this directly for local CPU (faster). */ DECLARE_PER_CPU(unsigned long, this_cpu_off); +#ifdef CONFIG_NEED_MULTIPLE_NODES +void *pcpu_lpage_remapped(void *kaddr); +#else +static inline void *pcpu_lpage_remapped(void *kaddr) +{ + return NULL; +} +#endif + #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_SMP diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 7d38941e2b8c5..bad2fd223114d 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -142,8 +142,8 @@ struct pcpul_ent { void *ptr; }; -static size_t pcpul_size __initdata; -static struct pcpul_ent *pcpul_map __initdata; +static size_t pcpul_size; +static struct pcpul_ent *pcpul_map; static struct vm_struct pcpul_vm; static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) @@ -160,15 +160,14 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) { size_t map_size, dyn_size; unsigned int cpu; + int i, j; ssize_t ret; /* * If large page isn't supported, there's no benefit in doing * this. Also, on non-NUMA, embedding is better. - * - * NOTE: disabled for now. */ - if (true || !cpu_has_pse || !pcpu_need_numa()) + if (!cpu_has_pse || !pcpu_need_numa()) return -EINVAL; /* @@ -231,16 +230,71 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) ret = pcpu_setup_first_chunk(pcpul_get_page, static_size, PERCPU_FIRST_CHUNK_RESERVE, dyn_size, PMD_SIZE, pcpul_vm.addr, NULL); - goto out_free_map; + + /* sort pcpul_map array for pcpu_lpage_remapped() */ + for (i = 0; i < num_possible_cpus() - 1; i++) + for (j = i + 1; j < num_possible_cpus(); j++) + if (pcpul_map[i].ptr > pcpul_map[j].ptr) { + struct pcpul_ent tmp = pcpul_map[i]; + pcpul_map[i] = pcpul_map[j]; + pcpul_map[j] = tmp; + } + + return ret; enomem: for_each_possible_cpu(cpu) if (pcpul_map[cpu].ptr) free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size); - ret = -ENOMEM; -out_free_map: free_bootmem(__pa(pcpul_map), map_size); - return ret; + return -ENOMEM; +} + +/** + * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area + * @kaddr: the kernel address in question + * + * Determine whether @kaddr falls in the pcpul recycled area. This is + * used by pageattr to detect VM aliases and break up the pcpu PMD + * mapping such that the same physical page is not mapped under + * different attributes. + * + * The recycled area is always at the tail of a partially used PMD + * page. + * + * RETURNS: + * Address of corresponding remapped pcpu address if match is found; + * otherwise, NULL. + */ +void *pcpu_lpage_remapped(void *kaddr) +{ + void *pmd_addr = (void *)((unsigned long)kaddr & PMD_MASK); + unsigned long offset = (unsigned long)kaddr & ~PMD_MASK; + int left = 0, right = num_possible_cpus() - 1; + int pos; + + /* pcpul in use at all? */ + if (!pcpul_map) + return NULL; + + /* okay, perform binary search */ + while (left <= right) { + pos = (left + right) / 2; + + if (pcpul_map[pos].ptr < pmd_addr) + left = pos + 1; + else if (pcpul_map[pos].ptr > pmd_addr) + right = pos - 1; + else { + /* it shouldn't be in the area for the first chunk */ + WARN_ON(offset < pcpul_size); + + return pcpul_vm.addr + + pcpul_map[pos].cpu * PMD_SIZE + offset; + } + } + + return NULL; } #else static ssize_t __init setup_pcpu_lpage(size_t static_size) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 2ab058b0947de..1b734d7a89668 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -11,6 +11,7 @@ #include <linux/interrupt.h> #include <linux/seq_file.h> #include <linux/debugfs.h> +#include <linux/pfn.h> #include <asm/e820.h> #include <asm/processor.h> @@ -682,7 +683,7 @@ static int cpa_process_alias(struct cpa_data *cpa) { struct cpa_data alias_cpa; unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT); - unsigned long vaddr; + unsigned long vaddr, remapped; int ret; if (cpa->pfn >= max_pfn_mapped) @@ -737,6 +738,24 @@ static int cpa_process_alias(struct cpa_data *cpa) } #endif + /* + * If the PMD page was partially used for per-cpu remapping, + * the recycled area needs to be split and modified. Because + * the area is always proper subset of a PMD page + * cpa->numpages is guaranteed to be 1 for these areas, so + * there's no need to loop over and check for further remaps. + */ + remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr); + if (remapped) { + WARN_ON(cpa->numpages > 1); + alias_cpa = *cpa; + alias_cpa.vaddr = &remapped; + alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); + ret = __change_page_attr_set_clr(&alias_cpa, 0); + if (ret) + return ret; + } + return 0; } -- GitLab From fa8a7094ba1679b4b9b443e0ac9f5e046c79ee8d Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0035/1002] x86: implement percpu_alloc kernel parameter According to Andi, it isn't clear whether lpage allocator is worth the trouble as there are many processors where PMD TLB is far scarcer than PTE TLB. The advantage or disadvantage probably depends on the actual size of percpu area and specific processor. As performance degradation due to TLB pressure tends to be highly workload specific and subtle, it is difficult to decide which way to go without more data. This patch implements percpu_alloc kernel parameter to allow selecting which first chunk allocator to use to ease debugging and testing. While at it, make sure all the failure paths report why something failed to help determining why certain allocator isn't working. Also, kill the "Great future plan" comment which had already been realized quite some time ago. [ Impact: allow explicit percpu first chunk allocator selection ] Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Jan Beulich <JBeulich@novell.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> --- Documentation/kernel-parameters.txt | 6 +++ arch/x86/kernel/setup_percpu.c | 69 +++++++++++++++++++++-------- mm/percpu.c | 13 ++++-- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 08def8deb5f57..ecad946920d1d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1882,6 +1882,12 @@ and is between 256 and 4096 characters. It is defined in the file Format: { 0 | 1 } See arch/parisc/kernel/pdc_chassis.c + percpu_alloc= [X86] Select which percpu first chunk allocator to use. + Allowed values are one of "lpage", "embed" and "4k". + See comments in arch/x86/kernel/setup_percpu.c for + details on each allocator. This parameter is primarily + for debugging and performance comparison. + pf. [PARIDE] See Documentation/blockdev/paride.txt. diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index bad2fd223114d..165ebd5ba83bc 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -156,20 +156,23 @@ static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) return virt_to_page(pcpul_map[cpu].ptr + off); } -static ssize_t __init setup_pcpu_lpage(size_t static_size) +static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) { size_t map_size, dyn_size; unsigned int cpu; int i, j; ssize_t ret; - /* - * If large page isn't supported, there's no benefit in doing - * this. Also, on non-NUMA, embedding is better. - */ - if (!cpu_has_pse || !pcpu_need_numa()) + /* on non-NUMA, embedding is better */ + if (!chosen && !pcpu_need_numa()) return -EINVAL; + /* need PSE */ + if (!cpu_has_pse) { + pr_warning("PERCPU: lpage allocator requires PSE\n"); + return -EINVAL; + } + /* * Currently supports only single page. Supporting multiple * pages won't be too difficult if it ever becomes necessary. @@ -191,8 +194,11 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) pcpul_map[cpu].cpu = cpu; pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); - if (!pcpul_map[cpu].ptr) + if (!pcpul_map[cpu].ptr) { + pr_warning("PERCPU: failed to allocate large page " + "for cpu%u\n", cpu); goto enomem; + } /* * Only use pcpul_size bytes and give back the rest. @@ -297,7 +303,7 @@ void *pcpu_lpage_remapped(void *kaddr) return NULL; } #else -static ssize_t __init setup_pcpu_lpage(size_t static_size) +static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) { return -EINVAL; } @@ -311,7 +317,7 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size) * mapping so that it can use PMD mapping without additional TLB * pressure. */ -static ssize_t __init setup_pcpu_embed(size_t static_size) +static ssize_t __init setup_pcpu_embed(size_t static_size, bool chosen) { size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; @@ -320,7 +326,7 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) * this. Also, embedding allocation doesn't play well with * NUMA. */ - if (!cpu_has_pse || pcpu_need_numa()) + if (!chosen && (!cpu_has_pse || pcpu_need_numa())) return -EINVAL; return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, @@ -370,8 +376,11 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) void *ptr; ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); - if (!ptr) + if (!ptr) { + pr_warning("PERCPU: failed to allocate " + "4k page for cpu%u\n", cpu); goto enomem; + } memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); pcpu4k_pages[j++] = virt_to_page(ptr); @@ -395,6 +404,16 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) return ret; } +/* for explicit first chunk allocator selection */ +static char pcpu_chosen_alloc[16] __initdata; + +static int __init percpu_alloc_setup(char *str) +{ + strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1); + return 0; +} +early_param("percpu_alloc", percpu_alloc_setup); + static inline void setup_percpu_segment(int cpu) { #ifdef CONFIG_X86_32 @@ -408,11 +427,6 @@ static inline void setup_percpu_segment(int cpu) #endif } -/* - * Great future plan: - * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. - * Always point %gs to its beginning - */ void __init setup_per_cpu_areas(void) { size_t static_size = __per_cpu_end - __per_cpu_start; @@ -429,9 +443,26 @@ void __init setup_per_cpu_areas(void) * of large page mappings. Please read comments on top of * each allocator for details. */ - ret = setup_pcpu_lpage(static_size); - if (ret < 0) - ret = setup_pcpu_embed(static_size); + ret = -EINVAL; + if (strlen(pcpu_chosen_alloc)) { + if (strcmp(pcpu_chosen_alloc, "4k")) { + if (!strcmp(pcpu_chosen_alloc, "lpage")) + ret = setup_pcpu_lpage(static_size, true); + else if (!strcmp(pcpu_chosen_alloc, "embed")) + ret = setup_pcpu_embed(static_size, true); + else + pr_warning("PERCPU: unknown allocator %s " + "specified\n", pcpu_chosen_alloc); + if (ret < 0) + pr_warning("PERCPU: %s allocator failed (%zd), " + "falling back to 4k\n", + pcpu_chosen_alloc, ret); + } + } else { + ret = setup_pcpu_lpage(static_size, false); + if (ret < 0) + ret = setup_pcpu_embed(static_size, false); + } if (ret < 0) ret = setup_pcpu_4k(static_size); if (ret < 0) diff --git a/mm/percpu.c b/mm/percpu.c index d06f4748271e4..b70f2acd88535 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -1233,6 +1233,7 @@ static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, ssize_t dyn_size, ssize_t unit_size) { + size_t chunk_size; unsigned int cpu; /* determine parameters and allocate */ @@ -1247,11 +1248,15 @@ ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, } else pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); - pcpue_ptr = __alloc_bootmem_nopanic( - num_possible_cpus() * pcpue_unit_size, - PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); - if (!pcpue_ptr) + chunk_size = pcpue_unit_size * num_possible_cpus(); + + pcpue_ptr = __alloc_bootmem_nopanic(chunk_size, PAGE_SIZE, + __pa(MAX_DMA_ADDRESS)); + if (!pcpue_ptr) { + pr_warning("PERCPU: failed to allocate %zu bytes for " + "embedding\n", chunk_size); return -ENOMEM; + } /* return the leftover and copy */ for_each_possible_cpu(cpu) { -- GitLab From 0017c869ddcb73069905d09f9e98e68627466237 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Mon, 22 Jun 2009 11:56:24 +0900 Subject: [PATCH 0036/1002] x86: ensure percpu lpage doesn't consume too much vmalloc space On extreme configuration (e.g. 32bit 32-way NUMA machine), lpage percpu first chunk allocator can consume too much of vmalloc space. Make it fall back to 4k allocator if the consumption goes over 20%. [ Impact: add sanity check for lpage percpu first chunk allocator ] Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Jan Beulich <JBeulich@novell.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/setup_percpu.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 165ebd5ba83bc..29a3eef7cf4af 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -163,9 +163,21 @@ static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) int i, j; ssize_t ret; - /* on non-NUMA, embedding is better */ - if (!chosen && !pcpu_need_numa()) - return -EINVAL; + if (!chosen) { + size_t vm_size = VMALLOC_END - VMALLOC_START; + size_t tot_size = num_possible_cpus() * PMD_SIZE; + + /* on non-NUMA, embedding is better */ + if (!pcpu_need_numa()) + return -EINVAL; + + /* don't consume more than 20% of vmalloc area */ + if (tot_size > vm_size / 5) { + pr_info("PERCPU: too large chunk size %zuMB for " + "large page remap\n", tot_size >> 20); + return -EINVAL; + } + } /* need PSE */ if (!cpu_has_pse) { -- GitLab From 8c52da503b7e4cf961807f11824e3258ef9f7f1c Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Thu, 18 Jun 2009 20:22:19 -0700 Subject: [PATCH 0037/1002] drm/i915: Add missing dependency on Intel AGP support. Users could accidentally enable AGP but not the Intel AGP support, and get a DRM that doesn't probe as a result. Bug #22358. Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c961fe415aef8..39b393d38bb3e 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -81,6 +81,7 @@ config DRM_I830 config DRM_I915 tristate "i915 driver" + depends on AGP_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT -- GitLab From 51e268423151fc7bb41945bde7843160b6a14c32 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Mon, 22 Jun 2009 16:43:14 +0530 Subject: [PATCH 0038/1002] perf_counter tools: Define separate declarations for H/W and S/W events Define separate declarations for H/W and S/W events to: 1. Shorten name to save some space so that we can add more members 2. Fix alignment 3. Avoid declaring HARDWARE/SOFTWARE again and again. Removed unused CR(x, y) Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245669194.17153.6.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 35d04da38d6a1..12abab3a0d631 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -18,30 +18,30 @@ struct event_symbol { char *symbol; }; -#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y -#define CR(x, y) .type = PERF_TYPE_##x, .config = y +#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x +#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x static struct event_symbol event_symbols[] = { - { C(HARDWARE, HW_CPU_CYCLES), "cpu-cycles", }, - { C(HARDWARE, HW_CPU_CYCLES), "cycles", }, - { C(HARDWARE, HW_INSTRUCTIONS), "instructions", }, - { C(HARDWARE, HW_CACHE_REFERENCES), "cache-references", }, - { C(HARDWARE, HW_CACHE_MISSES), "cache-misses", }, - { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branch-instructions", }, - { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branches", }, - { C(HARDWARE, HW_BRANCH_MISSES), "branch-misses", }, - { C(HARDWARE, HW_BUS_CYCLES), "bus-cycles", }, - - { C(SOFTWARE, SW_CPU_CLOCK), "cpu-clock", }, - { C(SOFTWARE, SW_TASK_CLOCK), "task-clock", }, - { C(SOFTWARE, SW_PAGE_FAULTS), "page-faults", }, - { C(SOFTWARE, SW_PAGE_FAULTS), "faults", }, - { C(SOFTWARE, SW_PAGE_FAULTS_MIN), "minor-faults", }, - { C(SOFTWARE, SW_PAGE_FAULTS_MAJ), "major-faults", }, - { C(SOFTWARE, SW_CONTEXT_SWITCHES), "context-switches", }, - { C(SOFTWARE, SW_CONTEXT_SWITCHES), "cs", }, - { C(SOFTWARE, SW_CPU_MIGRATIONS), "cpu-migrations", }, - { C(SOFTWARE, SW_CPU_MIGRATIONS), "migrations", }, + { CHW(CPU_CYCLES), "cpu-cycles", }, + { CHW(CPU_CYCLES), "cycles", }, + { CHW(INSTRUCTIONS), "instructions", }, + { CHW(CACHE_REFERENCES), "cache-references", }, + { CHW(CACHE_MISSES), "cache-misses", }, + { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", }, + { CHW(BRANCH_INSTRUCTIONS), "branches", }, + { CHW(BRANCH_MISSES), "branch-misses", }, + { CHW(BUS_CYCLES), "bus-cycles", }, + + { CSW(CPU_CLOCK), "cpu-clock", }, + { CSW(TASK_CLOCK), "task-clock", }, + { CSW(PAGE_FAULTS), "page-faults", }, + { CSW(PAGE_FAULTS), "faults", }, + { CSW(PAGE_FAULTS_MIN), "minor-faults", }, + { CSW(PAGE_FAULTS_MAJ), "major-faults", }, + { CSW(CONTEXT_SWITCHES), "context-switches", }, + { CSW(CONTEXT_SWITCHES), "cs", }, + { CSW(CPU_MIGRATIONS), "cpu-migrations", }, + { CSW(CPU_MIGRATIONS), "migrations", }, }; #define __PERF_COUNTER_FIELD(config, name) \ -- GitLab From 74d5b5889ea71a95d8924c08f8a7c6e2bdcbc0ba Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Mon, 22 Jun 2009 16:44:28 +0530 Subject: [PATCH 0039/1002] perf_counter tools: Introduce alias member in event_symbol By introducing alias member in event_symbol : 1. duplicate lines are removed, like: cpu-cycles and cycles branch-instructions and branches context-switches and cs cpu-migrations and migrations 2. We can also add alias for another events. Now ./perf list looks like : List of pre-defined events (to be used in -e): cpu-cycles OR cycles [Hardware event] instructions [Hardware event] cache-references [Hardware event] cache-misses [Hardware event] branch-instructions OR branches [Hardware event] branch-misses [Hardware event] bus-cycles [Hardware event] cpu-clock [Software event] task-clock [Software event] page-faults [Software event] faults [Software event] minor-faults [Software event] major-faults [Software event] context-switches OR cs [Software event] cpu-migrations OR migrations [Software event] rNNN [raw hardware event descriptor] Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245669268.17153.8.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 63 ++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 12abab3a0d631..f5695486ad3f2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -16,32 +16,29 @@ struct event_symbol { u8 type; u64 config; char *symbol; + char *alias; }; #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x static struct event_symbol event_symbols[] = { - { CHW(CPU_CYCLES), "cpu-cycles", }, - { CHW(CPU_CYCLES), "cycles", }, - { CHW(INSTRUCTIONS), "instructions", }, - { CHW(CACHE_REFERENCES), "cache-references", }, - { CHW(CACHE_MISSES), "cache-misses", }, - { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", }, - { CHW(BRANCH_INSTRUCTIONS), "branches", }, - { CHW(BRANCH_MISSES), "branch-misses", }, - { CHW(BUS_CYCLES), "bus-cycles", }, - - { CSW(CPU_CLOCK), "cpu-clock", }, - { CSW(TASK_CLOCK), "task-clock", }, - { CSW(PAGE_FAULTS), "page-faults", }, - { CSW(PAGE_FAULTS), "faults", }, - { CSW(PAGE_FAULTS_MIN), "minor-faults", }, - { CSW(PAGE_FAULTS_MAJ), "major-faults", }, - { CSW(CONTEXT_SWITCHES), "context-switches", }, - { CSW(CONTEXT_SWITCHES), "cs", }, - { CSW(CPU_MIGRATIONS), "cpu-migrations", }, - { CSW(CPU_MIGRATIONS), "migrations", }, + { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, + { CHW(INSTRUCTIONS), "instructions", "" }, + { CHW(CACHE_REFERENCES), "cache-references", "" }, + { CHW(CACHE_MISSES), "cache-misses", "" }, + { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, + { CHW(BRANCH_MISSES), "branch-misses", "" }, + { CHW(BUS_CYCLES), "bus-cycles", "" }, + + { CSW(CPU_CLOCK), "cpu-clock", "" }, + { CSW(TASK_CLOCK), "task-clock", "" }, + { CSW(PAGE_FAULTS), "page-faults", "" }, + { CSW(PAGE_FAULTS), "faults", "" }, + { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, + { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, + { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, + { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, }; #define __PERF_COUNTER_FIELD(config, name) \ @@ -196,6 +193,19 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a return 0; } +static int check_events(const char *str, unsigned int i) +{ + if (!strncmp(str, event_symbols[i].symbol, + strlen(event_symbols[i].symbol))) + return 1; + + if (strlen(event_symbols[i].alias)) + if (!strncmp(str, event_symbols[i].alias, + strlen(event_symbols[i].alias))) + return 1; + return 0; +} + /* * Each event can have multiple symbolic names. * Symbolic names are (almost) exactly matched. @@ -235,9 +245,7 @@ static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) } for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { - if (!strncmp(str, event_symbols[i].symbol, - strlen(event_symbols[i].symbol))) { - + if (check_events(str, i)) { attr->type = event_symbols[i].type; attr->config = event_symbols[i].config; @@ -289,6 +297,7 @@ void print_events(void) { struct event_symbol *syms = event_symbols; unsigned int i, type, prev_type = -1; + char name[40]; fprintf(stderr, "\n"); fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); @@ -301,14 +310,18 @@ void print_events(void) if (type != prev_type) fprintf(stderr, "\n"); - fprintf(stderr, " %-30s [%s]\n", syms->symbol, + if (strlen(syms->alias)) + sprintf(name, "%s OR %s", syms->symbol, syms->alias); + else + strcpy(name, syms->symbol); + fprintf(stderr, " %-40s [%s]\n", name, event_type_descriptors[type]); prev_type = type; } fprintf(stderr, "\n"); - fprintf(stderr, " %-30s [raw hardware event descriptor]\n", + fprintf(stderr, " %-40s [raw hardware event descriptor]\n", "rNNN"); fprintf(stderr, "\n"); -- GitLab From 520f2c346af463fa00924b236e092da482b344cc Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <peterz@infradead.org> Date: Mon, 22 Jun 2009 16:52:51 +0200 Subject: [PATCH 0040/1002] perf report: Output more symbol related debug data Print more symbol relocation related info under -vv. Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 5 +++-- tools/perf/util/symbol.c | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5eb5566f0c954..ec230a0146e9f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -797,7 +797,7 @@ resolve_symbol(struct thread *thread, struct map **mapp, { struct dso *dso = dsop ? *dsop : NULL; struct map *map = mapp ? *mapp : NULL; - uint64_t ip = *ipp; + u64 ip = *ipp; if (!thread) return NULL; @@ -814,7 +814,6 @@ resolve_symbol(struct thread *thread, struct map **mapp, *mapp = map; got_map: ip = map->map_ip(map, ip); - *ipp = ip; dso = map->dso; } else { @@ -828,6 +827,8 @@ resolve_symbol(struct thread *thread, struct map **mapp, dso = kernel_dso; } dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); + dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip); + *ipp = ip; if (dsop) *dsop = dso; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 01b62fa039964..9c659ef6aec2d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -535,6 +535,10 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, gelf_getshdr(sec, &shdr); obj_start = sym.st_value; + if (verbose >= 2) + printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", + (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); + sym.st_value -= shdr.sh_addr - shdr.sh_offset; f = symbol__new(sym.st_value, sym.st_size, -- GitLab From c0c22dbfa8ba3c5045eeb9c76d2822ffc44fefc3 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Mon, 22 Jun 2009 20:47:26 +0530 Subject: [PATCH 0041/1002] perf_counter tools: Set alias for page-faults "faults" should be alias for "page-faults" Also fixed alignment and 80 characters issue Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245683846.12092.1.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index f5695486ad3f2..06af2fadcd870 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -33,8 +33,7 @@ static struct event_symbol event_symbols[] = { { CSW(CPU_CLOCK), "cpu-clock", "" }, { CSW(TASK_CLOCK), "task-clock", "" }, - { CSW(PAGE_FAULTS), "page-faults", "" }, - { CSW(PAGE_FAULTS), "faults", "" }, + { CSW(PAGE_FAULTS), "page-faults", "faults" }, { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, @@ -71,24 +70,24 @@ static char *sw_event_names[] = { #define MAX_ALIASES 8 -static char *hw_cache [][MAX_ALIASES] = { - { "L1-data" , "l1-d", "l1d" }, - { "L1-instruction" , "l1-i", "l1i" }, - { "L2" , "l2" }, - { "Data-TLB" , "dtlb", "d-tlb" }, - { "Instruction-TLB" , "itlb", "i-tlb" }, - { "Branch" , "bpu" , "btb", "bpc" }, +static char *hw_cache[][MAX_ALIASES] = { + { "L1-data", "l1-d", "l1d" }, + { "L1-instruction", "l1-i", "l1i" }, + { "L2", "l2" }, + { "Data-TLB", "dtlb", "d-tlb" }, + { "Instruction-TLB", "itlb", "i-tlb" }, + { "Branch", "bpu" , "btb", "bpc" }, }; -static char *hw_cache_op [][MAX_ALIASES] = { - { "Load" , "read" }, - { "Store" , "write" }, - { "Prefetch" , "speculative-read", "speculative-load" }, +static char *hw_cache_op[][MAX_ALIASES] = { + { "Load", "read" }, + { "Store", "write" }, + { "Prefetch", "speculative-read", "speculative-load" }, }; -static char *hw_cache_result [][MAX_ALIASES] = { - { "Reference" , "ops", "access" }, - { "Miss" }, +static char *hw_cache_result[][MAX_ALIASES] = { + { "Reference", "ops", "access" }, + { "Miss" }, }; char *event_name(int counter) @@ -160,7 +159,8 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) return -1; } -static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) +static int +parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) { int cache_type = -1, cache_op = 0, cache_result = 0; @@ -201,7 +201,7 @@ static int check_events(const char *str, unsigned int i) if (strlen(event_symbols[i].alias)) if (!strncmp(str, event_symbols[i].alias, - strlen(event_symbols[i].alias))) + strlen(event_symbols[i].alias))) return 1; return 0; } -- GitLab From 4839641333d4593bfc4fb29aa3af10d36f607d5b Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Tue, 23 Jun 2009 01:34:19 +0100 Subject: [PATCH 0042/1002] jffs2: fix another potential leak on error path in scan.c Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- fs/jffs2/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 7515e73e2bfbd..696686cc206e1 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -130,9 +130,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (jffs2_sum_active()) { s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); if (!s) { - kfree(flashbuf); JFFS2_WARNING("Can't allocate memory for summary\n"); - return -ENOMEM; + ret = -ENOMEM; + goto out; } } -- GitLab From 9e06dd39f2b6d7e35981e0d7aded618686b32ccb Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 22 Jun 2009 18:05:12 -0700 Subject: [PATCH 0043/1002] drm/i915: correct suspend/resume ordering We need to save register state *after* idling GEM, clearing the ring, and uninstalling the IRQ handler, or we might end up saving bogus fence regs, for one. Our restore ordering should already be correct, since we do GEM, ring and IRQ init after restoring the last register state, which prevents us from clobbering things. I put this together to potentially address a bug, but I haven't heard back if it fixes it yet. However I think it stands on its own, so I'm sending it in. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 98560e1e899a8..e3cb4025e323c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -67,8 +67,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) pci_save_state(dev->pdev); - i915_save_state(dev); - /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (i915_gem_idle(dev)) @@ -77,6 +75,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) drm_irq_uninstall(dev); } + i915_save_state(dev); + intel_opregion_free(dev, 1); if (state.event == PM_EVENT_SUSPEND) { -- GitLab From 3fbe18d65d66054667aaee849bed74674bb50062 Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Mon, 22 Jun 2009 15:31:25 +0800 Subject: [PATCH 0044/1002] drm/i915: Add support for changing LVDS panel fitting using an output property. Previously the driver would always scale the chosen video mode to fill the panel. This adds 1:1 and maintain-aspect-ratio scaling modes. v2: the drm_calloc/drm_free is replaced by kzalloc/kfree based on Eric's suggestion. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_reg.h | 16 ++ drivers/gpu/drm/i915/intel_lvds.c | 285 +++++++++++++++++++++++++++--- 2 files changed, 280 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 544d5677a2fa2..88bf7521405f5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -847,9 +847,25 @@ #define HORIZ_INTERP_MASK (3 << 6) #define HORIZ_AUTO_SCALE (1 << 5) #define PANEL_8TO6_DITHER_ENABLE (1 << 3) +#define PFIT_FILTER_FUZZY (0 << 24) +#define PFIT_SCALING_AUTO (0 << 26) +#define PFIT_SCALING_PROGRAMMED (1 << 26) +#define PFIT_SCALING_PILLAR (2 << 26) +#define PFIT_SCALING_LETTER (3 << 26) #define PFIT_PGM_RATIOS 0x61234 #define PFIT_VERT_SCALE_MASK 0xfff00000 #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* Pre-965 */ +#define PFIT_VERT_SCALE_SHIFT 20 +#define PFIT_VERT_SCALE_MASK 0xfff00000 +#define PFIT_HORIZ_SCALE_SHIFT 4 +#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* 965+ */ +#define PFIT_VERT_SCALE_SHIFT_965 16 +#define PFIT_VERT_SCALE_MASK_965 0x1fff0000 +#define PFIT_HORIZ_SCALE_SHIFT_965 0 +#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff + #define PFIT_AUTO_RATIOS 0x61238 /* Backlight control */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 345e5055f1c0f..f416ead71204d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -39,6 +39,21 @@ #define I915_LVDS "i915_lvds" +/* + * the following four scaling options are defined. + * #define DRM_MODE_SCALE_NON_GPU 0 + * #define DRM_MODE_SCALE_FULLSCREEN 1 + * #define DRM_MODE_SCALE_NO_SCALE 2 + * #define DRM_MODE_SCALE_ASPECT 3 + */ + +/* Private structure for the integrated LVDS support */ +struct intel_lvds_priv { + int fitting_mode; + u32 pfit_control; + u32 pfit_pgm_ratios; +}; + /** * Sets the backlight level. * @@ -213,10 +228,24 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + /* + * float point operation is not supported . So the PANEL_RATIO_FACTOR + * is defined, which can avoid the float point computation when + * calculating the panel ratio. + */ +#define PANEL_RATIO_FACTOR 8192 struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct drm_encoder *tmp_encoder; + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; + u32 pfit_control = 0, pfit_pgm_ratios = 0; + int left_border = 0, right_border = 0, top_border = 0; + int bottom_border = 0; + bool border = 0; + int panel_ratio, desired_ratio, vert_scale, horiz_scale; + int horiz_ratio, vert_ratio; /* Should never happen!! */ if (!IS_I965G(dev) && intel_crtc->pipe == 0) { @@ -232,7 +261,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, return false; } } - + /* If we don't have a panel mode, there is nothing we can do */ + if (dev_priv->panel_fixed_mode == NULL) + return true; /* * If we have timings from the BIOS for the panel, put them in * to the adjusted mode. The CRTC will be set up for this mode, @@ -256,6 +287,191 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); } + /* Make sure pre-965s set dither correctly */ + if (!IS_I965G(dev)) { + if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) + pfit_control |= PANEL_8TO6_DITHER_ENABLE; + } + + /* Native modes don't need fitting */ + if (adjusted_mode->hdisplay == mode->hdisplay && + adjusted_mode->vdisplay == mode->vdisplay) { + pfit_pgm_ratios = 0; + border = 0; + goto out; + } + + /* 965+ wants fuzzy fitting */ + if (IS_I965G(dev)) + pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | + PFIT_FILTER_FUZZY; + + /* + * Deal with panel fitting options. Figure out how to stretch the + * image based on its aspect ratio & the current panel fitting mode. + */ + panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR / + adjusted_mode->vdisplay; + desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR / + mode->vdisplay; + /* + * Enable automatic panel scaling for non-native modes so that they fill + * the screen. Should be enabled before the pipe is enabled, according + * to register description and PRM. + * Change the value here to see the borders for debugging + */ + I915_WRITE(BCLRPAT_A, 0); + I915_WRITE(BCLRPAT_B, 0); + + switch (lvds_priv->fitting_mode) { + case DRM_MODE_SCALE_NO_SCALE: + /* + * For centered modes, we have to calculate border widths & + * heights and modify the values programmed into the CRTC. + */ + left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2; + right_border = left_border; + if (mode->hdisplay & 1) + right_border++; + top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2; + bottom_border = top_border; + if (mode->vdisplay & 1) + bottom_border++; + /* Set active & border values */ + adjusted_mode->crtc_hdisplay = mode->hdisplay; + adjusted_mode->crtc_hblank_start = mode->hdisplay + + right_border - 1; + adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal - + left_border - 1; + adjusted_mode->crtc_hsync_start = + adjusted_mode->crtc_hblank_start; + adjusted_mode->crtc_hsync_end = + adjusted_mode->crtc_hblank_end; + adjusted_mode->crtc_vdisplay = mode->vdisplay; + adjusted_mode->crtc_vblank_start = mode->vdisplay + + bottom_border - 1; + adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal - + top_border - 1; + adjusted_mode->crtc_vsync_start = + adjusted_mode->crtc_vblank_start; + adjusted_mode->crtc_vsync_end = + adjusted_mode->crtc_vblank_end; + border = 1; + break; + case DRM_MODE_SCALE_ASPECT: + /* Scale but preserve the spect ratio */ + pfit_control |= PFIT_ENABLE; + if (IS_I965G(dev)) { + /* 965+ is easy, it does everything in hw */ + if (panel_ratio > desired_ratio) + pfit_control |= PFIT_SCALING_PILLAR; + else if (panel_ratio < desired_ratio) + pfit_control |= PFIT_SCALING_LETTER; + else + pfit_control |= PFIT_SCALING_AUTO; + } else { + /* + * For earlier chips we have to calculate the scaling + * ratio by hand and program it into the + * PFIT_PGM_RATIO register + */ + u32 horiz_bits, vert_bits, bits = 12; + horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/ + adjusted_mode->hdisplay; + vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/ + adjusted_mode->vdisplay; + horiz_scale = adjusted_mode->hdisplay * + PANEL_RATIO_FACTOR / mode->hdisplay; + vert_scale = adjusted_mode->vdisplay * + PANEL_RATIO_FACTOR / mode->vdisplay; + + /* retain aspect ratio */ + if (panel_ratio > desired_ratio) { /* Pillar */ + u32 scaled_width; + scaled_width = mode->hdisplay * vert_scale / + PANEL_RATIO_FACTOR; + horiz_ratio = vert_ratio; + pfit_control |= (VERT_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + /* Pillar will have left/right borders */ + left_border = (adjusted_mode->hdisplay - + scaled_width) / 2; + right_border = left_border; + if (mode->hdisplay & 1) /* odd resolutions */ + right_border++; + adjusted_mode->crtc_hdisplay = scaled_width; + adjusted_mode->crtc_hblank_start = + scaled_width + right_border - 1; + adjusted_mode->crtc_hblank_end = + adjusted_mode->crtc_htotal - left_border - 1; + adjusted_mode->crtc_hsync_start = + adjusted_mode->crtc_hblank_start; + adjusted_mode->crtc_hsync_end = + adjusted_mode->crtc_hblank_end; + border = 1; + } else if (panel_ratio < desired_ratio) { /* letter */ + u32 scaled_height = mode->vdisplay * + horiz_scale / PANEL_RATIO_FACTOR; + vert_ratio = horiz_ratio; + pfit_control |= (HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + /* Letterbox will have top/bottom border */ + top_border = (adjusted_mode->vdisplay - + scaled_height) / 2; + bottom_border = top_border; + if (mode->vdisplay & 1) + bottom_border++; + adjusted_mode->crtc_vdisplay = scaled_height; + adjusted_mode->crtc_vblank_start = + scaled_height + bottom_border - 1; + adjusted_mode->crtc_vblank_end = + adjusted_mode->crtc_vtotal - top_border - 1; + adjusted_mode->crtc_vsync_start = + adjusted_mode->crtc_vblank_start; + adjusted_mode->crtc_vsync_end = + adjusted_mode->crtc_vblank_end; + border = 1; + } else { + /* Aspects match, Let hw scale both directions */ + pfit_control |= (VERT_AUTO_SCALE | + HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + } + horiz_bits = (1 << bits) * horiz_ratio / + PANEL_RATIO_FACTOR; + vert_bits = (1 << bits) * vert_ratio / + PANEL_RATIO_FACTOR; + pfit_pgm_ratios = + ((vert_bits << PFIT_VERT_SCALE_SHIFT) & + PFIT_VERT_SCALE_MASK) | + ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) & + PFIT_HORIZ_SCALE_MASK); + } + break; + + case DRM_MODE_SCALE_FULLSCREEN: + /* + * Full scaling, even if it changes the aspect ratio. + * Fortunately this is all done for us in hw. + */ + pfit_control |= PFIT_ENABLE; + if (IS_I965G(dev)) + pfit_control |= PFIT_SCALING_AUTO; + else + pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_INTERP_BILINEAR); + break; + default: + break; + } + +out: + lvds_priv->pfit_control = pfit_control; + lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; /* * XXX: It would be nice to support lower refresh rates on the * panels to reduce power consumption, and perhaps match the @@ -301,8 +517,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, { struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - u32 pfit_control; + struct intel_output *intel_output = enc_to_intel_output(encoder); + struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; /* * The LVDS pin pair will already have been turned on in the @@ -319,22 +535,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, * screen. Should be enabled before the pipe is enabled, according to * register description and PRM. */ - if (mode->hdisplay != adjusted_mode->hdisplay || - mode->vdisplay != adjusted_mode->vdisplay) - pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | - HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - else - pfit_control = 0; - - if (!IS_I965G(dev)) { - if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) - pfit_control |= PANEL_8TO6_DITHER_ENABLE; - } - else - pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; - - I915_WRITE(PFIT_CONTROL, pfit_control); + I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); + I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); } /** @@ -406,6 +608,34 @@ static int intel_lvds_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t value) { + struct drm_device *dev = connector->dev; + struct intel_output *intel_output = + to_intel_output(connector); + + if (property == dev->mode_config.scaling_mode_property && + connector->encoder) { + struct drm_crtc *crtc = connector->encoder->crtc; + struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; + if (value == DRM_MODE_SCALE_NON_GPU) { + DRM_DEBUG_KMS(I915_LVDS, + "non_GPU property is unsupported\n"); + return 0; + } + if (lvds_priv->fitting_mode == value) { + /* the LVDS scaling property is not changed */ + return 0; + } + lvds_priv->fitting_mode = value; + if (crtc && crtc->enabled) { + /* + * If the CRTC is enabled, the display will be changed + * according to the new panel fitting mode. + */ + drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, crtc->fb); + } + } + return 0; } @@ -518,6 +748,7 @@ void intel_lvds_init(struct drm_device *dev) struct drm_encoder *encoder; struct drm_display_mode *scan; /* *modes, *bios_mode; */ struct drm_crtc *crtc; + struct intel_lvds_priv *lvds_priv; u32 lvds; int pipe, gpio = GPIOC; @@ -531,7 +762,8 @@ void intel_lvds_init(struct drm_device *dev) gpio = PCH_GPIOC; } - intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); + intel_output = kzalloc(sizeof(struct intel_output) + + sizeof(struct intel_lvds_priv), GFP_KERNEL); if (!intel_output) { return; } @@ -553,7 +785,18 @@ void intel_lvds_init(struct drm_device *dev) connector->interlace_allowed = false; connector->doublescan_allowed = false; + lvds_priv = (struct intel_lvds_priv *)(intel_output + 1); + intel_output->dev_priv = lvds_priv; + /* create the scaling mode property */ + drm_mode_create_scaling_mode_property(dev); + /* + * the initial panel fitting mode will be FULL_SCREEN. + */ + drm_connector_attach_property(&intel_output->base, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; /* * LVDS discovery: * 1) check for EDID on DDC @@ -649,5 +892,5 @@ void intel_lvds_init(struct drm_device *dev) if (intel_output->ddc_bus) intel_i2c_destroy(intel_output->ddc_bus); drm_connector_cleanup(connector); - kfree(connector); + kfree(intel_output); } -- GitLab From aa0261f230105b86409e29bbe851b09830d93d50 Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Mon, 22 Jun 2009 15:31:26 +0800 Subject: [PATCH 0045/1002] drm/i915: Don't change the blank/sync width when calculating scaled modes Also, use the border instead of border minus one. At the same time, make sure the horizontal border and hsync are even for the LVDS that works in dual-channel mode. So both horizontal border and hsync start are also changed to be even, even for the LVDS in single-channel mode. https://bugs.freedesktop.org/show_bug.cgi?id=20951 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_lvds.c | 91 +++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f416ead71204d..9564ca44a977e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -246,6 +246,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, bool border = 0; int panel_ratio, desired_ratio, vert_scale, horiz_scale; int horiz_ratio, vert_ratio; + u32 hsync_width, vsync_width; + u32 hblank_width, vblank_width; + u32 hsync_pos, vsync_pos; /* Should never happen!! */ if (!IS_I965G(dev) && intel_crtc->pipe == 0) { @@ -306,6 +309,14 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | PFIT_FILTER_FUZZY; + hsync_width = adjusted_mode->crtc_hsync_end - + adjusted_mode->crtc_hsync_start; + vsync_width = adjusted_mode->crtc_vsync_end - + adjusted_mode->crtc_vsync_start; + hblank_width = adjusted_mode->crtc_hblank_end - + adjusted_mode->crtc_hblank_start; + vblank_width = adjusted_mode->crtc_vblank_end - + adjusted_mode->crtc_vblank_start; /* * Deal with panel fitting options. Figure out how to stretch the * image based on its aspect ratio & the current panel fitting mode. @@ -339,23 +350,39 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, bottom_border++; /* Set active & border values */ adjusted_mode->crtc_hdisplay = mode->hdisplay; + /* Keep the boder be even */ + if (right_border & 1) + right_border++; + /* use the border directly instead of border minuse one */ adjusted_mode->crtc_hblank_start = mode->hdisplay + - right_border - 1; - adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal - - left_border - 1; + right_border; + /* keep the blank width constant */ + adjusted_mode->crtc_hblank_end = + adjusted_mode->crtc_hblank_start + hblank_width; + /* get the hsync pos relative to hblank start */ + hsync_pos = (hblank_width - hsync_width) / 2; + /* keep the hsync pos be even */ + if (hsync_pos & 1) + hsync_pos++; adjusted_mode->crtc_hsync_start = - adjusted_mode->crtc_hblank_start; + adjusted_mode->crtc_hblank_start + hsync_pos; + /* keep the hsync width constant */ adjusted_mode->crtc_hsync_end = - adjusted_mode->crtc_hblank_end; + adjusted_mode->crtc_hsync_start + hsync_width; adjusted_mode->crtc_vdisplay = mode->vdisplay; + /* use the border instead of border minus one */ adjusted_mode->crtc_vblank_start = mode->vdisplay + - bottom_border - 1; - adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal - - top_border - 1; + bottom_border; + /* keep the vblank width constant */ + adjusted_mode->crtc_vblank_end = + adjusted_mode->crtc_vblank_start + vblank_width; + /* get the vsync start postion relative to vblank start */ + vsync_pos = (vblank_width - vsync_width) / 2; adjusted_mode->crtc_vsync_start = - adjusted_mode->crtc_vblank_start; + adjusted_mode->crtc_vblank_start + vsync_pos; + /* keep the vsync width constant */ adjusted_mode->crtc_vsync_end = - adjusted_mode->crtc_vblank_end; + adjusted_mode->crtc_vblank_start + vsync_width; border = 1; break; case DRM_MODE_SCALE_ASPECT: @@ -400,15 +427,32 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, right_border = left_border; if (mode->hdisplay & 1) /* odd resolutions */ right_border++; + /* keep the border be even */ + if (right_border & 1) + right_border++; adjusted_mode->crtc_hdisplay = scaled_width; + /* use border instead of border minus one */ adjusted_mode->crtc_hblank_start = - scaled_width + right_border - 1; + scaled_width + right_border; + /* keep the hblank width constant */ adjusted_mode->crtc_hblank_end = - adjusted_mode->crtc_htotal - left_border - 1; + adjusted_mode->crtc_hblank_start + + hblank_width; + /* + * get the hsync start pos relative to + * hblank start + */ + hsync_pos = (hblank_width - hsync_width) / 2; + /* keep the hsync_pos be even */ + if (hsync_pos & 1) + hsync_pos++; adjusted_mode->crtc_hsync_start = - adjusted_mode->crtc_hblank_start; + adjusted_mode->crtc_hblank_start + + hsync_pos; + /* keept hsync width constant */ adjusted_mode->crtc_hsync_end = - adjusted_mode->crtc_hblank_end; + adjusted_mode->crtc_hsync_start + + hsync_width; border = 1; } else if (panel_ratio < desired_ratio) { /* letter */ u32 scaled_height = mode->vdisplay * @@ -424,14 +468,25 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, if (mode->vdisplay & 1) bottom_border++; adjusted_mode->crtc_vdisplay = scaled_height; + /* use border instead of border minus one */ adjusted_mode->crtc_vblank_start = - scaled_height + bottom_border - 1; + scaled_height + bottom_border; + /* keep the vblank width constant */ adjusted_mode->crtc_vblank_end = - adjusted_mode->crtc_vtotal - top_border - 1; + adjusted_mode->crtc_vblank_start + + vblank_width; + /* + * get the vsync start pos relative to + * vblank start + */ + vsync_pos = (vblank_width - vsync_width) / 2; adjusted_mode->crtc_vsync_start = - adjusted_mode->crtc_vblank_start; + adjusted_mode->crtc_vblank_start + + vsync_pos; + /* keep the vsync width constant */ adjusted_mode->crtc_vsync_end = - adjusted_mode->crtc_vblank_end; + adjusted_mode->crtc_vsync_start + + vsync_width; border = 1; } else { /* Aspects match, Let hw scale both directions */ -- GitLab From cfd43c025ddef0b1c723bb9811d2bde52b285710 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa <khc@pm.waw.pl> Date: Sat, 20 Jun 2009 00:31:28 +0200 Subject: [PATCH 0046/1002] drm/i915: Fix size_t handling in off-by-default debug printfs Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem.c | 6 +++--- drivers/gpu/drm/i915/i915_gem_debug.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fd2b8bdffe3f4..8660b2144b27a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1006,7 +1006,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); #if WATCH_BUF - DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n", + DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", obj, obj->size, read_domains, write_domain); #endif if (read_domains & I915_GEM_DOMAIN_GTT) { @@ -1050,7 +1050,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, } #if WATCH_BUF - DRM_INFO("%s: sw_finish %d (%p %d)\n", + DRM_INFO("%s: sw_finish %d (%p %zd)\n", __func__, args->handle, obj, obj->size); #endif obj_priv = obj->driver_private; @@ -2423,7 +2423,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) } #if WATCH_BUF - DRM_INFO("Binding object of size %d at 0x%08x\n", + DRM_INFO("Binding object of size %zd at 0x%08x\n", obj->size, obj_priv->gtt_offset); #endif ret = i915_gem_object_get_pages(obj); diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 8d0b943e2c5ac..f94b5985f734c 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) uint32_t *backing_map = NULL; int bad_count = 0; - DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n", + DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n", __func__, obj, obj_priv->gtt_offset, handle, obj->size / 1024); -- GitLab From 921809a5831821eaf86e799c4b3d7c666ee352b1 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa <khc@pm.waw.pl> Date: Fri, 19 Jun 2009 22:35:09 +0200 Subject: [PATCH 0047/1002] drm/i915: Catch up to obj_priv->page_list rename in disabled debug code. Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem_debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index f94b5985f734c..e602614bd3f89 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, chunk_len = page_len - chunk; if (chunk_len > 128) chunk_len = 128; - i915_gem_dump_page(obj_priv->page_list[page], + i915_gem_dump_page(obj_priv->pages[page], chunk, chunk + chunk_len, obj_priv->gtt_offset + page * PAGE_SIZE, @@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) for (page = 0; page < obj->size / PAGE_SIZE; page++) { int i; - backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0); + backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0); if (backing_map == NULL) { DRM_ERROR("failed to map backing page\n"); -- GitLab From 8ed9a5bc9c9425ef93a1b03b418300a5e18b2361 Mon Sep 17 00:00:00 2001 From: "ling.ma@intel.com" <ling.ma@intel.com> Date: Mon, 22 Jun 2009 22:08:35 +0800 Subject: [PATCH 0048/1002] drm/i915: set TV detection mode when tv is already connected We used load_detect_temp flag to determine whether to set tv to the test mode. However if the TV already has a mode set, we still need to set the test mode to determine connection. This results in blinking, but there is no other reliable way to determine TV connection. freedesktop.org bug #22035 Signed-off-by: Ma Ling <ling.ma@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_tv.c | 53 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index ea68992e44160..a43c98e3f0777 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) /* * Detect TV by polling) */ - if (intel_output->load_detect_temp) { - /* TV not currently running, prod it with destructive detect */ - save_tv_dac = tv_dac; - tv_ctl = I915_READ(TV_CTL); - save_tv_ctl = tv_ctl; - tv_ctl &= ~TV_ENC_ENABLE; - tv_ctl &= ~TV_TEST_MODE_MASK; - tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; - tv_dac &= ~TVDAC_SENSE_MASK; - tv_dac &= ~DAC_A_MASK; - tv_dac &= ~DAC_B_MASK; - tv_dac &= ~DAC_C_MASK; - tv_dac |= (TVDAC_STATE_CHG_EN | - TVDAC_A_SENSE_CTL | - TVDAC_B_SENSE_CTL | - TVDAC_C_SENSE_CTL | - DAC_CTL_OVERRIDE | - DAC_A_0_7_V | - DAC_B_0_7_V | - DAC_C_0_7_V); - I915_WRITE(TV_CTL, tv_ctl); - I915_WRITE(TV_DAC, tv_dac); - intel_wait_for_vblank(dev); - tv_dac = I915_READ(TV_DAC); - I915_WRITE(TV_DAC, save_tv_dac); - I915_WRITE(TV_CTL, save_tv_ctl); - intel_wait_for_vblank(dev); - } + save_tv_dac = tv_dac; + tv_ctl = I915_READ(TV_CTL); + save_tv_ctl = tv_ctl; + tv_ctl &= ~TV_ENC_ENABLE; + tv_ctl &= ~TV_TEST_MODE_MASK; + tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; + tv_dac &= ~TVDAC_SENSE_MASK; + tv_dac &= ~DAC_A_MASK; + tv_dac &= ~DAC_B_MASK; + tv_dac &= ~DAC_C_MASK; + tv_dac |= (TVDAC_STATE_CHG_EN | + TVDAC_A_SENSE_CTL | + TVDAC_B_SENSE_CTL | + TVDAC_C_SENSE_CTL | + DAC_CTL_OVERRIDE | + DAC_A_0_7_V | + DAC_B_0_7_V | + DAC_C_0_7_V); + I915_WRITE(TV_CTL, tv_ctl); + I915_WRITE(TV_DAC, tv_dac); + intel_wait_for_vblank(dev); + tv_dac = I915_READ(TV_DAC); + I915_WRITE(TV_DAC, save_tv_dac); + I915_WRITE(TV_CTL, save_tv_ctl); + intel_wait_for_vblank(dev); /* * A B C * 0 1 1 Composite -- GitLab From 1b16de0b070dc6fa29b7a99980eabe3325ee5983 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 22 Jun 2009 11:30:30 -0700 Subject: [PATCH 0049/1002] drm/i915: fix LFP data fetch Apparently the proper way to do this is to use the LFP data pointer block to figure out the LFP data block entry size, then use that plus the panel index to calculate an offset into the LFP data block array. Similar fix has already been pushed to the 2D driver to fix fdo bug applied to the VBIOS reader, and things look sane). Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_bios.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index cdd126d068a72..716409a57244b 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -99,9 +99,11 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, { struct bdb_lvds_options *lvds_options; struct bdb_lvds_lfp_data *lvds_lfp_data; + struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; struct bdb_lvds_lfp_data_entry *entry; struct lvds_dvo_timing *dvo_timing; struct drm_display_mode *panel_fixed_mode; + int lfp_data_size; /* Defaults if we can't find VBT info */ dev_priv->lvds_dither = 0; @@ -119,9 +121,17 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, if (!lvds_lfp_data) return; + lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); + if (!lvds_lfp_data_ptrs) + return; + dev_priv->lvds_vbt = 1; - entry = &lvds_lfp_data->data[lvds_options->panel_type]; + lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - + lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; + entry = (struct bdb_lvds_lfp_data_entry *) + ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * + lvds_options->panel_type)); dvo_timing = &entry->dvo_timing; panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); -- GitLab From 56d21b07d44e0a33ab846f4f08e9e33bd87e5d4b Mon Sep 17 00:00:00 2001 From: Zhenyu Wang <zhenyuw@linux.intel.com> Date: Wed, 17 Jun 2009 09:43:25 +0800 Subject: [PATCH 0050/1002] drm/i915: Fix HDMI regression introduced in new chipset support Remove wrongly added NULL_PACKETS_DURING_VSYNC setting for HDMI. Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_hdmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 3955476eb64f8..9e30daae37dca 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -57,8 +57,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE | SDVO_VSYNC_ACTIVE_HIGH | - SDVO_HSYNC_ACTIVE_HIGH | - SDVO_NULL_PACKETS_DURING_VSYNC; + SDVO_HSYNC_ACTIVE_HIGH; if (hdmi_priv->has_hdmi_sink) sdvox |= SDVO_AUDIO_ENABLE; -- GitLab From dee412066aeb16c43cf31599948c1a1de385df56 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Tue, 23 Jun 2009 02:22:39 +0530 Subject: [PATCH 0051/1002] perf stat: Fix command option / manpage -l is not supported, it should be -S for scale. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245703959.6167.16.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Documentation/perf-stat.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index c368a72721d78..0d74346d21abd 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics SYNOPSIS -------- [verse] -'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] <command> -'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] -- <command> [<options>] +'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command> +'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>] DESCRIPTION ----------- @@ -40,7 +40,7 @@ OPTIONS -a:: system-wide collection --l:: +-S:: scale counter values EXAMPLES -- GitLab From 854c879f5abf309ebd378bea1ee41acf4ddf7194 Mon Sep 17 00:00:00 2001 From: Pekka J Enberg <penberg@cs.helsinki.fi> Date: Mon, 22 Jun 2009 17:39:41 +0300 Subject: [PATCH 0052/1002] x86: Move init_gbpages() to setup_arch() The init_gbpages() function is conditionally called from init_memory_mapping() function. There are two call-sites where this 'after_bootmem' condition can be true: setup_arch() and mem_init() via pci_iommu_alloc(). Therefore, it's safe to move the call to init_gbpages() to setup_arch() as it's always called before mem_init(). This removes an after_bootmem use - paving the way to remove all uses of that state variable. Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> Acked-by: Yinghai Lu <yinghai@kernel.org> LKML-Reference: <Pine.LNX.4.64.0906221731210.19474@melkki.cs.Helsinki.FI> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/setup.c | 16 ++++++++++++++++ arch/x86/mm/init.c | 17 ----------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index be5ae80f897fb..de2cab1328449 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -289,6 +289,20 @@ void * __init extend_brk(size_t size, size_t align) return ret; } +#ifdef CONFIG_X86_64 +static void __init init_gbpages(void) +{ + if (direct_gbpages && cpu_has_gbpages) + printk(KERN_INFO "Using GB pages for direct mapping\n"); + else + direct_gbpages = 0; +} +#else +static inline void init_gbpages(void) +{ +} +#endif + static void __init reserve_brk(void) { if (_brk_end > _brk_start) @@ -871,6 +885,8 @@ void __init setup_arch(char **cmdline_p) reserve_brk(); + init_gbpages(); + /* max_pfn_mapped is updated here */ max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); max_pfn_mapped = max_low_pfn_mapped; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index f53b57e4086ff..47ce9a2ce5e7c 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -177,20 +177,6 @@ static int __meminit save_mr(struct map_range *mr, int nr_range, return nr_range; } -#ifdef CONFIG_X86_64 -static void __init init_gbpages(void) -{ - if (direct_gbpages && cpu_has_gbpages) - printk(KERN_INFO "Using GB pages for direct mapping\n"); - else - direct_gbpages = 0; -} -#else -static inline void init_gbpages(void) -{ -} -#endif - /* * Setup the direct mapping of the physical memory at PAGE_OFFSET. * This runs before bootmem is initialized and gets pages directly from @@ -210,9 +196,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end); - if (!after_bootmem) - init_gbpages(); - #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK) /* * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. -- GitLab From bfdb4d9f0f611687d71cf6a460efc9e755f4a462 Mon Sep 17 00:00:00 2001 From: Arun R Bharadwaj <arun@linux.vnet.ibm.com> Date: Tue, 23 Jun 2009 10:00:58 +0530 Subject: [PATCH 0053/1002] timers: Fix timer_migration interface which accepts any number as input Poornima Nayek reported: | Timer migration interface /proc/sys/kernel/timer_migration in | 2.6.30-git9 accepts any numerical value as input. | | Steps to reproduce: | 1. echo -6666666 > /proc/sys/kernel/timer_migration | 2. cat /proc/sys/kernel/timer_migration | -6666666 | | 1. echo 44444444444444444444444444444444444444444444444444444444444 > /proc/sys/kernel/timer_migration | 2. cat /proc/sys/kernel/timer_migration | -1357789412 | | Expected behavior: Should 'echo: write error: Invalid argument' while | setting any value other then 0 & 1 Restrict valid values to 0 and 1. Reported-by: Poornima Nayak <mpnayak@linux.vnet.ibm.com> Tested-by: Poornima Nayak <mpnayak@linux.vnet.ibm.com> Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com> Cc: poornima nayak <mpnayak@linux.vnet.ibm.com> Cc: Arun Bharadwaj <arun@linux.vnet.ibm.com> LKML-Reference: <20090623043058.GA3249@linux.vnet.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/sysctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 62e4ff9968b5f..c428ba161db1e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -335,7 +335,10 @@ static struct ctl_table kern_table[] = { .data = &sysctl_timer_migration, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + .extra2 = &one, }, #endif { -- GitLab From 3d906ef10a539ff336010afab8f6f9c4fe379695 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Tue, 23 Jun 2009 11:23:07 +0200 Subject: [PATCH 0054/1002] perf_counter tools: Handle overlapping MMAP events Martin Schwidefsky reported "perf report" symbol resolution problems on S390. Since we only report MMAP, not MUNMAP, we have to deal with overlapping maps. We used to simply throw out the old map on the assumption whole maps got unmapped. This obviously doesn't deal with partial unmaps. However it appears some dynamic linkers do fancy partial unmaps (s390), so do something more elaborate and truncate the old maps, only removing them when they've been fully covered. This resolves (part of) the S390 symbol resolution problems. Reported-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Tested-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ec230a0146e9f..b4e76f75ba87f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -400,9 +400,27 @@ static void thread__insert_map(struct thread *self, struct map *map) list_for_each_entry_safe(pos, tmp, &self->maps, node) { if (map__overlap(pos, map)) { - list_del_init(&pos->node); - /* XXX leaks dsos */ - free(pos); + if (verbose >= 2) { + printf("overlapping maps:\n"); + map__fprintf(map, stdout); + map__fprintf(pos, stdout); + } + + if (map->start <= pos->start && map->end > pos->start) + pos->start = map->end; + + if (map->end >= pos->end && map->start < pos->end) + pos->end = map->start; + + if (verbose >= 2) { + printf("after collision:\n"); + map__fprintf(pos, stdout); + } + + if (pos->start >= pos->end) { + list_del_init(&pos->node); + free(pos); + } } } -- GitLab From f29ac756a40d0f1bb07d682ea521e7b666ff06d5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Fri, 19 Jun 2009 18:27:26 +0200 Subject: [PATCH 0055/1002] perf_counter: Optimize perf_swcounter_event() Similar to tracepoints, use an enable variable to reduce overhead when unused. Only look for a counter of a particular event type when we know there is at least one in the system. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 11 ++++++++++- kernel/perf_counter.c | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 89698d8aba5c1..e7213e46cf9c5 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -669,7 +669,16 @@ static inline int is_software_counter(struct perf_counter *counter) (counter->attr.type != PERF_TYPE_HW_CACHE); } -extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64); +extern atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX]; + +extern void __perf_swcounter_event(u32, u64, int, struct pt_regs *, u64); + +static inline void +perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) +{ + if (atomic_read(&perf_swcounter_enabled[event])) + __perf_swcounter_event(event, nr, nmi, regs, addr); +} extern void __perf_counter_mmap(struct vm_area_struct *vma); diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 1a933a221ea4a..7515c76954281 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -3317,8 +3317,8 @@ static void do_perf_swcounter_event(enum perf_type_id type, u32 event, put_cpu_var(perf_cpu_context); } -void -perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) +void __perf_swcounter_event(u32 event, u64 nr, int nmi, + struct pt_regs *regs, u64 addr) { struct perf_sample_data data = { .regs = regs, @@ -3509,9 +3509,19 @@ static const struct pmu *tp_perf_counter_init(struct perf_counter *counter) } #endif +atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX]; + +static void sw_perf_counter_destroy(struct perf_counter *counter) +{ + u64 event = counter->attr.config; + + atomic_dec(&perf_swcounter_enabled[event]); +} + static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) { const struct pmu *pmu = NULL; + u64 event = counter->attr.config; /* * Software counters (currently) can't in general distinguish @@ -3520,7 +3530,7 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) * to be kernel events, and page faults are never hypervisor * events. */ - switch (counter->attr.config) { + switch (event) { case PERF_COUNT_SW_CPU_CLOCK: pmu = &perf_ops_cpu_clock; @@ -3541,6 +3551,8 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) case PERF_COUNT_SW_PAGE_FAULTS_MAJ: case PERF_COUNT_SW_CONTEXT_SWITCHES: case PERF_COUNT_SW_CPU_MIGRATIONS: + atomic_inc(&perf_swcounter_enabled[event]); + counter->destroy = sw_perf_counter_destroy; pmu = &perf_ops_generic; break; } -- GitLab From b84fbc9fb1d943e2c5f4efe52ed0e3c93a4bdb6a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Mon, 22 Jun 2009 13:57:40 +0200 Subject: [PATCH 0056/1002] perf_counter: Push inherit into perf_counter_alloc() Teach perf_counter_alloc() about inheritance so that we can optimize the inherit path in the next patch. Remove the child_counter->atrr.inherit = 1 line because the only way to get there is if parent_counter->attr.inherit == 1 and we copy the attrs. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/perf_counter.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 7515c76954281..0a45490f40291 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -3568,6 +3568,7 @@ perf_counter_alloc(struct perf_counter_attr *attr, int cpu, struct perf_counter_context *ctx, struct perf_counter *group_leader, + struct perf_counter *parent_counter, gfp_t gfpflags) { const struct pmu *pmu; @@ -3603,6 +3604,8 @@ perf_counter_alloc(struct perf_counter_attr *attr, counter->ctx = ctx; counter->oncpu = -1; + counter->parent = parent_counter; + counter->ns = get_pid_ns(current->nsproxy->pid_ns); counter->id = atomic64_inc_return(&perf_counter_id); @@ -3827,7 +3830,7 @@ SYSCALL_DEFINE5(perf_counter_open, } counter = perf_counter_alloc(&attr, cpu, ctx, group_leader, - GFP_KERNEL); + NULL, GFP_KERNEL); ret = PTR_ERR(counter); if (IS_ERR(counter)) goto err_put_context; @@ -3893,7 +3896,8 @@ inherit_counter(struct perf_counter *parent_counter, child_counter = perf_counter_alloc(&parent_counter->attr, parent_counter->cpu, child_ctx, - group_leader, GFP_KERNEL); + group_leader, parent_counter, + GFP_KERNEL); if (IS_ERR(child_counter)) return child_counter; get_ctx(child_ctx); @@ -3916,12 +3920,6 @@ inherit_counter(struct perf_counter *parent_counter, */ add_counter_to_ctx(child_counter, child_ctx); - child_counter->parent = parent_counter; - /* - * inherit into child's child as well: - */ - child_counter->attr.inherit = 1; - /* * Get a reference to the parent filp - we will fput it * when the child counter exits. This is safe to do because -- GitLab From f344011ccb85469445369153c3d27c4ee4bc2ac8 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Mon, 22 Jun 2009 13:58:35 +0200 Subject: [PATCH 0057/1002] perf_counter: Optimize perf_counter_alloc()'s inherit case We don't need to add usage counts for swcounter and attr usage models for inherited counters since the parent counter will always have one, which suffices to generate the needed output. This avoids up to 3 global atomic increments per inherited counter. LKML-Reference: <new-submission> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/perf_counter.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 0a45490f40291..c2b19c1117187 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1508,11 +1508,13 @@ static void free_counter(struct perf_counter *counter) { perf_pending_sync(counter); - atomic_dec(&nr_counters); - if (counter->attr.mmap) - atomic_dec(&nr_mmap_counters); - if (counter->attr.comm) - atomic_dec(&nr_comm_counters); + if (!counter->parent) { + atomic_dec(&nr_counters); + if (counter->attr.mmap) + atomic_dec(&nr_mmap_counters); + if (counter->attr.comm) + atomic_dec(&nr_comm_counters); + } if (counter->destroy) counter->destroy(counter); @@ -3515,6 +3517,8 @@ static void sw_perf_counter_destroy(struct perf_counter *counter) { u64 event = counter->attr.config; + WARN_ON(counter->parent); + atomic_dec(&perf_swcounter_enabled[event]); } @@ -3551,8 +3555,10 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) case PERF_COUNT_SW_PAGE_FAULTS_MAJ: case PERF_COUNT_SW_CONTEXT_SWITCHES: case PERF_COUNT_SW_CPU_MIGRATIONS: - atomic_inc(&perf_swcounter_enabled[event]); - counter->destroy = sw_perf_counter_destroy; + if (!counter->parent) { + atomic_inc(&perf_swcounter_enabled[event]); + counter->destroy = sw_perf_counter_destroy; + } pmu = &perf_ops_generic; break; } @@ -3663,11 +3669,13 @@ perf_counter_alloc(struct perf_counter_attr *attr, counter->pmu = pmu; - atomic_inc(&nr_counters); - if (counter->attr.mmap) - atomic_inc(&nr_mmap_counters); - if (counter->attr.comm) - atomic_inc(&nr_comm_counters); + if (!counter->parent) { + atomic_inc(&nr_counters); + if (counter->attr.mmap) + atomic_inc(&nr_mmap_counters); + if (counter->attr.comm) + atomic_inc(&nr_comm_counters); + } return counter; } -- GitLab From 0c405b3346ea08098a82a1ee82912b018dfa9f96 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell <noodles@earth.li> Date: Tue, 23 Jun 2009 13:30:21 +0300 Subject: [PATCH 0058/1002] OMAP1: Fix compilation of arch/arm/mach-omap1/mailbox.c This fixes the positioning of " in MODULE_AUTHOR, which is currently causing a build failure on latest git with CONFIG_OMAP_MBOX_FWK=m; the original breakage appears to date from the end of last year in a5abbbe52b7e89a7633319c5417bd4331f7ac8ed Signed-Off-By: Jonathan McDowell <noodles@earth.li> Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap1/mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c index 0af4d6c85b476..6810b4aeb02cd 100644 --- a/arch/arm/mach-omap1/mailbox.c +++ b/arch/arm/mach-omap1/mailbox.c @@ -203,5 +203,5 @@ module_exit(omap1_mbox_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions"); -MODULE_AUTHOR("Hiroshi DOYU" <Hiroshi.DOYU@nokia.com>); +MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>"); MODULE_ALIAS("platform:omap1-mailbox"); -- GitLab From e4d24ec39c98cdc9cd97c26fdd426bbab0034fbe Mon Sep 17 00:00:00 2001 From: Andrew de Quincey <adq_dvb@lidskialf.net> Date: Tue, 23 Jun 2009 13:30:21 +0300 Subject: [PATCH 0059/1002] OMAP1: Fix N770 MMC support Some of the N770's MMC configuration options seem to have been dropped. This patch adds them back in again. Note that only the .ocr_mask change was /critical/, but I've added the .max_freq setting back as well, as the original sources had it. Can anyone confirm if this is unnecessary? Secondly, there is support in the original code for a 4wire/higher speed mode. As I don't have the requisite N770 hardware (I think it was a rev2 N770?) to test this, I can't really add it back. Signed-off-by: Andrew de Quincey <adq@lidskialf.net> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap1/board-nokia770.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index e70fc7c66bbb6..d9ebba01ffcee 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -205,9 +205,11 @@ static int nokia770_mmc_get_cover_state(struct device *dev, int slot) static struct omap_mmc_platform_data nokia770_mmc2_data = { .nr_slots = 1, .dma_mask = 0xffffffff, + .max_freq = 12000000, .slots[0] = { .set_power = nokia770_mmc_set_power, .get_cover_state = nokia770_mmc_get_cover_state, + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .name = "mmcblk", }, }; -- GitLab From d376f89701b0aa5b45d25fbfbeb1a0040399ad30 Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Tue, 23 Jun 2009 13:30:22 +0300 Subject: [PATCH 0060/1002] OMAP1: remove duplicated #include Remove duplicated #include in arch/arm/mach-omap1/board-nokia770.c. Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap1/board-nokia770.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index d9ebba01ffcee..ed2a48a9ce74b 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -36,7 +36,6 @@ #include <mach/hwa742.h> #include <mach/lcd_mipid.h> #include <mach/mmc.h> -#include <mach/usb.h> #include <mach/clock.h> #define ADS7846_PENDOWN_GPIO 15 -- GitLab From 762ad3a476baa1831f732488e80960f4aa024393 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas <notasas@gmail.com> Date: Tue, 23 Jun 2009 13:30:22 +0300 Subject: [PATCH 0061/1002] OMAP2/3: mmc-twl4030: use correct controller in twl_mmc23_set_power twl_mmc23_set_power() has MMC2 twl_mmc_controller hardcoded in it, which breaks MMC3. Find the right controller to use instead. Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/mmc-twl4030.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 9756a878fd902..1541fd4c8d0fd 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -263,8 +263,19 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd) { int ret = 0; - struct twl_mmc_controller *c = &hsmmc[1]; + struct twl_mmc_controller *c = NULL; struct omap_mmc_platform_data *mmc = dev->platform_data; + int i; + + for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { + if (mmc == hsmmc[i].mmc) { + c = &hsmmc[i]; + break; + } + } + + if (c == NULL) + return -ENODEV; /* If we don't see a Vcc regulator, assume it's a fixed * voltage always-on regulator. -- GitLab From 091a58af0ba1765d80b1e74382c7572baceb1bdc Mon Sep 17 00:00:00 2001 From: Roel Kluin <roel.kluin@gmail.com> Date: Tue, 23 Jun 2009 13:30:22 +0300 Subject: [PATCH 0062/1002] OMAP2/3: omap mailbox: platform_get_irq() error ignored platform_get_irq may return -ENXIO. but struct omap_mbox mbox_dsp_info.irq is unsigned, so the error was not noticed. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/mailbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index fd5b8a5925cc5..6f71f3730c977 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -282,12 +282,12 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev) return -ENOMEM; /* DSP or IVA2 IRQ */ - mbox_dsp_info.irq = platform_get_irq(pdev, 0); - if (mbox_dsp_info.irq < 0) { + ret = platform_get_irq(pdev, 0); + if (ret < 0) { dev_err(&pdev->dev, "invalid irq resource\n"); - ret = -ENODEV; goto err_dsp; } + mbox_dsp_info.irq = ret; ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info); if (ret) -- GitLab From 8e25ad964aac0bf6b30dd013303750089f819679 Mon Sep 17 00:00:00 2001 From: Kevin Hilman <khilman@deeprootsystems.com> Date: Tue, 23 Jun 2009 13:30:23 +0300 Subject: [PATCH 0063/1002] OMAP2/3: Add omap_type() for determining GP/EMU/HS The omap_type() function is added and returns the DEVICETYPE field of the CONTROL_STATUS register. The result can be used for conditional code based on whether device is GP (general purpose), EMU or HS (high security). Also move the type defines so omap1 code compile does not require ifdefs for sections using these defines. This code is needed for the following fix to set the SRAM size correctly for HS omaps. Also at least PM and watchdog code will need this function. Signed-off-by: Kevin Hilman <khilman@ti.deeprootsystems.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/id.c | 22 ++++++++++++++++++++++ arch/arm/plat-omap/include/mach/cpu.h | 22 +++++++++++----------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 458990e20c60d..a98201cc265cc 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -48,6 +48,28 @@ int omap_chip_is(struct omap_chip_id oci) } EXPORT_SYMBOL(omap_chip_is); +int omap_type(void) +{ + u32 val = 0; + + if (cpu_is_omap24xx()) + val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS); + else if (cpu_is_omap34xx()) + val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS); + else { + pr_err("Cannot detect omap type!\n"); + goto out; + } + + val &= OMAP2_DEVICETYPE_MASK; + val >>= 8; + +out: + return val; +} +EXPORT_SYMBOL(omap_type); + + /*----------------------------------------------------------------------------*/ #define OMAP_TAP_IDCODE 0x0204 diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index fc60c4ebcc28a..285eaa3a82750 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -30,6 +30,17 @@ #ifndef __ASM_ARCH_OMAP_CPU_H #define __ASM_ARCH_OMAP_CPU_H +/* + * Omap device type i.e. EMU/HS/TST/GP/BAD + */ +#define OMAP2_DEVICE_TYPE_TEST 0 +#define OMAP2_DEVICE_TYPE_EMU 1 +#define OMAP2_DEVICE_TYPE_SEC 2 +#define OMAP2_DEVICE_TYPE_GP 3 +#define OMAP2_DEVICE_TYPE_BAD 4 + +int omap_type(void); + struct omap_chip_id { u8 oc; u8 type; @@ -424,17 +435,6 @@ IS_OMAP_TYPE(3430, 0x3430) int omap_chip_is(struct omap_chip_id oci); -int omap_type(void); - -/* - * Macro to detect device type i.e. EMU/HS/TST/GP/BAD - */ -#define OMAP2_DEVICE_TYPE_TEST 0 -#define OMAP2_DEVICE_TYPE_EMU 1 -#define OMAP2_DEVICE_TYPE_SEC 2 -#define OMAP2_DEVICE_TYPE_GP 3 -#define OMAP2_DEVICE_TYPE_BAD 4 - void omap2_check_revision(void); #endif /* defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) */ -- GitLab From 5b0acc59d1bc5c310dfd6976555664f9dcf4dacd Mon Sep 17 00:00:00 2001 From: Tero Kristo <tero.kristo@nokia.com> Date: Tue, 23 Jun 2009 13:30:23 +0300 Subject: [PATCH 0064/1002] OMAP3: SRAM size fix for HS/EMU devices SRAM size fix for HS/EMU devices Signed-off-by: Tero Kristo <tero.kristo@nokia.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/plat-omap/sram.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 65006df3f1b75..4ea73804d21e2 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -133,7 +133,12 @@ void __init omap_detect_sram(void) if (cpu_is_omap34xx()) { omap_sram_base = OMAP3_SRAM_PUB_VA; omap_sram_start = OMAP3_SRAM_PUB_PA; - omap_sram_size = 0x8000; /* 32K */ + if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) || + (omap_type() == OMAP2_DEVICE_TYPE_SEC)) { + omap_sram_size = 0x7000; /* 28K */ + } else { + omap_sram_size = 0x8000; /* 32K */ + } } else { omap_sram_base = OMAP2_SRAM_PUB_VA; omap_sram_start = OMAP2_SRAM_PUB_PA; -- GitLab From aecedb94b366d6fb5e2a17ca18a5dc78e593198e Mon Sep 17 00:00:00 2001 From: Kalle Jokiniemi <ext-kalle.jokiniemi@nokia.com> Date: Tue, 23 Jun 2009 13:30:24 +0300 Subject: [PATCH 0065/1002] OMAP3: DMA: Enable idlemodes for DMA OCP This patch enables MStandby smart-idle mode, autoidle smartidle mode, and the autoidle bit for DMA4_OCP_SYSCONFIG. Signed-off-by: Kalle Jokiniemi <ext-kalle.jokiniemi@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Kevin Hilman <khilman@ti.deeprootsystems.com> --- arch/arm/plat-omap/dma.c | 13 +++++++++++++ arch/arm/plat-omap/include/mach/dma.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index def14ec265b36..7677a4a1cef26 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -2457,6 +2457,19 @@ static int __init omap_init_dma(void) setup_irq(irq, &omap24xx_dma_irq); } + /* Enable smartidle idlemodes and autoidle */ + if (cpu_is_omap34xx()) { + u32 v = dma_read(OCP_SYSCONFIG); + v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | + DMA_SYSCONFIG_SIDLEMODE_MASK | + DMA_SYSCONFIG_AUTOIDLE); + v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | + DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | + DMA_SYSCONFIG_AUTOIDLE); + dma_write(v , OCP_SYSCONFIG); + } + + /* FIXME: Update LCD DMA to work on 24xx */ if (cpu_class_is_omap1()) { r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 8c1eae88737e9..7b939cc019620 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -389,6 +389,21 @@ #define DMA_THREAD_FIFO_25 (0x02 << 14) #define DMA_THREAD_FIFO_50 (0x03 << 14) +/* DMA4_OCP_SYSCONFIG bits */ +#define DMA_SYSCONFIG_MIDLEMODE_MASK (3 << 12) +#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK (3 << 8) +#define DMA_SYSCONFIG_EMUFREE (1 << 5) +#define DMA_SYSCONFIG_SIDLEMODE_MASK (3 << 3) +#define DMA_SYSCONFIG_SOFTRESET (1 << 2) +#define DMA_SYSCONFIG_AUTOIDLE (1 << 0) + +#define DMA_SYSCONFIG_MIDLEMODE(n) ((n) << 12) +#define DMA_SYSCONFIG_SIDLEMODE(n) ((n) << 3) + +#define DMA_IDLEMODE_SMARTIDLE 0x2 +#define DMA_IDLEMODE_NO_IDLE 0x1 +#define DMA_IDLEMODE_FORCE_IDLE 0x0 + /* Chaining modes*/ #ifndef CONFIG_ARCH_OMAP1 #define OMAP_DMA_STATIC_CHAIN 0x1 -- GitLab From 6d453e84b587f38e4197bb2c6a37296c4a80cbac Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Tue, 23 Jun 2009 13:30:24 +0300 Subject: [PATCH 0066/1002] OMAP2/3: gpmc-onenand: correct use of async timings Use async timings when sync timings are not requested. Also ensure that OneNAND is in async mode when async timings are used. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/gpmc-onenand.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 2fd22f9c5f0e7..54fec53a48e7a 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -31,6 +31,8 @@ static struct platform_device gpmc_onenand_device = { static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) { struct gpmc_timings t; + u32 reg; + int err; const int t_cer = 15; const int t_avdp = 12; @@ -43,6 +45,11 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; + /* Ensure sync read and sync write are disabled */ + reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; + writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); + memset(&t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -74,7 +81,16 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - return gpmc_cs_set_timings(cs, &t); + err = gpmc_cs_set_timings(cs, &t); + if (err) + return err; + + /* Ensure sync read and sync write are disabled */ + reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE; + writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); + + return 0; } static void set_onenand_cfg(void __iomem *onenand_base, int latency, @@ -124,7 +140,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, } else if (cfg->flags & ONENAND_SYNC_READWRITE) { sync_read = 1; sync_write = 1; - } + } else + return omap2_onenand_set_async_mode(cs, onenand_base); if (!freq) { /* Very first call freq is not known */ -- GitLab From c8e6488f7b56d82453fc7d526118e9f1c2df133a Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Tue, 23 Jun 2009 13:30:25 +0300 Subject: [PATCH 0067/1002] OMAP3: RX51: Use OneNAND sync read / write Use OneNAND sync read / write Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/board-rx51-peripherals.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index da93b86234ed4..9a0bf6744a057 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -362,6 +362,7 @@ static struct omap_onenand_platform_data board_onenand_data = { .gpio_irq = 65, .parts = onenand_partitions, .nr_parts = ARRAY_SIZE(onenand_partitions), + .flags = ONENAND_SYNC_READWRITE, }; static void __init board_onenand_init(void) -- GitLab From f48ef99ca14577f3ea0a48c0e05ed7f5f6d211e9 Mon Sep 17 00:00:00 2001 From: Fernando Guzman Lugo <x0095840@ti.com> Date: Tue, 23 Jun 2009 13:30:25 +0300 Subject: [PATCH 0068/1002] OMAP: IOMMU: function flush_iotlb_page is not flushing correct entry The function flush_iotlb_page is not loading the CAM register with the correct entry to be flushed, so it is flushing other entry Signed-off-by: Fernando Guzman Lugo <x0095840@ti.com> Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/plat-omap/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 4cf449fa2cb54..4a03013990135 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -298,7 +298,7 @@ void flush_iotlb_page(struct iommu *obj, u32 da) if ((start <= da) && (da < start + bytes)) { dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", __func__, start, da, bytes); - + iotlb_load_cr(obj, &cr); iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); } } -- GitLab From cb5793db5ecf108594d8006ae838e47996a76a19 Mon Sep 17 00:00:00 2001 From: janboe <janboe.ye@gmail.com> Date: Tue, 23 Jun 2009 13:30:25 +0300 Subject: [PATCH 0069/1002] OMAP2/3: Initialize gpio debounce register Some bootloader may initialize debounce register and this will make dbclk not consist with the debounce register after linux kernel boot up. Signed-off-by: janboe <janboe.ye@gmail.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/plat-omap/gpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 7fd89ba8d3b59..26b387c124239 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -1585,6 +1585,7 @@ static int __init _omap_gpio_init(void) __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1); __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1); __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG); + __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_DEBOUNCE_EN); /* Initialize interface clock ungated, module enabled */ __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); -- GitLab From 291e99a112f9bf34c027031de7ef8b94a2692937 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Mon, 4 May 2009 09:30:51 +0100 Subject: [PATCH 0070/1002] [ARM] S3C24XX: Fix use of CONFIG_S3C24XX_PWM CONFIG_S3C24XX_PWM was defined in arch/arm/plat-s3c24xx/Kconfig but not used anywhere else as the corresponding makefile used CONFIG_HAVE_PWM (selected by CONFIG_S3C24XX_PWM) to compile the PWM driver. Change the makefile to use CONFIG_S3C24XX_PWM to compile this driver to ensure it is only build when needed. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/plat-s3c24xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index 636cb12711df8..579a165c28270 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += irq-pm.o obj-$(CONFIG_PM) += sleep.o -obj-$(CONFIG_HAVE_PWM) += pwm.o +obj-$(CONFIG_S3C24XX_PWM) += pwm.o obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o obj-$(CONFIG_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C24XX_ADC) += adc.o -- GitLab From a18327f35a879a6467c3e901da7f68944b191732 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Mon, 4 May 2009 09:53:12 +0100 Subject: [PATCH 0071/1002] [ARM] S3C: Remove unused CONFIG_DEBUG_S3C_PORT Remove the unused CONFIG_DEBUG_S3C_PORT as we currently only have support for using the S3C UARTs via the low-level debug code. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/Kconfig.debug | 8 -------- arch/arm/configs/s3c2410_defconfig | 1 - arch/arm/configs/s3c6400_defconfig | 1 - arch/arm/configs/tct_hammer_defconfig | 1 - 4 files changed, 11 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index a71fd941ade7c..a89e4734b8f0b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -99,14 +99,6 @@ config DEBUG_CLPS711X_UART2 output to the second serial port on these devices. Saying N will cause the debug messages to appear on the first serial port. -config DEBUG_S3C_PORT - depends on DEBUG_LL && PLAT_S3C - bool "Kernel low-level debugging messages via S3C UART" - help - Say Y here if you want debug print routines to go to one of the - S3C internal UARTs. The chosen UART must have been configured - before it is used. - config DEBUG_S3C_UART depends on PLAT_S3C int "S3C UART to use for low-level debug" diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 2d58b8fe59bed..f4f1899f3c885 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -2298,7 +2298,6 @@ CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set -CONFIG_DEBUG_S3C_PORT=y CONFIG_DEBUG_S3C_UART=0 # diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig index 2e8fa50e9a09a..32860609e0577 100644 --- a/arch/arm/configs/s3c6400_defconfig +++ b/arch/arm/configs/s3c6400_defconfig @@ -816,7 +816,6 @@ CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set -CONFIG_DEBUG_S3C_PORT=y CONFIG_DEBUG_S3C_UART=0 # diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig index 07dfb98df4f07..9d32faef05f6e 100644 --- a/arch/arm/configs/tct_hammer_defconfig +++ b/arch/arm/configs/tct_hammer_defconfig @@ -857,7 +857,6 @@ CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set -# CONFIG_DEBUG_S3C_PORT is not set CONFIG_DEBUG_S3C_UART=0 # -- GitLab From f49156ea1bf3bccf45a01351cf3db2b5f6a8597e Mon Sep 17 00:00:00 2001 From: Timur Tabi <timur@freescale.com> Date: Tue, 26 May 2009 10:21:42 -0500 Subject: [PATCH 0072/1002] powerpc/qe: add polling timeout to qe_issue_cmd() The qe_issue_cmd() function (Freescale PowerPC QUICC Engine library) polls on a register until a status bit changes, but does not include a timeout to handle the situation if the bit never changes. Change the code to use the new spin_event_timeout() macro, which simplifies polling on a register without a timeout. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/sysdev/qe_lib/qe.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index b28b0e512d67d..237e3654f48ca 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c @@ -112,6 +112,7 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) { unsigned long flags; u8 mcn_shift = 0, dev_shift = 0; + u32 ret; spin_lock_irqsave(&qe_lock, flags); if (cmd == QE_RESET) { @@ -139,11 +140,13 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) } /* wait for the QE_CR_FLG to clear */ - while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) - cpu_relax(); + ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0, + 100, 0); + /* On timeout (e.g. failure), the expression will be false (ret == 0), + otherwise it will be true (ret == 1). */ spin_unlock_irqrestore(&qe_lock, flags); - return 0; + return ret == 1; } EXPORT_SYMBOL(qe_issue_cmd); -- GitLab From 5e10cf587a7b1aa34099cbfc244e6f04e96dc835 Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Tue, 19 May 2009 00:52:20 -0500 Subject: [PATCH 0073/1002] powerpc/cpm1: Remove IMAP_ADDR We no longer user IMAP_ADDR for anything so kill it off. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/include/asm/cpm1.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 2ff798744c1d6..7685ffde88210 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -598,8 +598,6 @@ typedef struct risc_timer_pram { #define CICR_IEN ((uint)0x00000080) /* Int. enable */ #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ -#define IMAP_ADDR (get_immrbase()) - #define CPM_PIN_INPUT 0 #define CPM_PIN_OUTPUT 1 #define CPM_PIN_PRIMARY 0 -- GitLab From a44a23ed4d144e4fb83d256b32021b732bda4787 Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Thu, 18 Jun 2009 23:28:34 -0500 Subject: [PATCH 0074/1002] powerpc/85xx: Stop using ppc_md.init on socrates Match what other 85xx platforms do for of_platform_bus_probe and use machine_device_initcall. This is one small step in killing of ppc_md.init. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/platforms/85xx/socrates.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c index d0e8443b12c64..747d8fb3ab82a 100644 --- a/arch/powerpc/platforms/85xx/socrates.c +++ b/arch/powerpc/platforms/85xx/socrates.c @@ -102,10 +102,11 @@ static struct of_device_id __initdata socrates_of_bus_ids[] = { {}, }; -static void __init socrates_init(void) +static int __init socrates_publish_devices(void) { - of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL); + return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL); } +machine_device_initcall(socrates, socrates_publish_devices); /* * Called very early, device-tree isn't unflattened @@ -124,7 +125,6 @@ define_machine(socrates) { .name = "Socrates", .probe = socrates_probe, .setup_arch = socrates_setup_arch, - .init = socrates_init, .init_IRQ = socrates_pic_init, .get_irq = mpic_get_irq, .restart = fsl_rstcr_restart, -- GitLab From fa874618c3155e4f255387987d630a203578b5ae Mon Sep 17 00:00:00 2001 From: Randy Vinson <rvinson@mvista.com> Date: Fri, 19 Jun 2009 03:22:08 +0400 Subject: [PATCH 0075/1002] powerpc/85xx: Fix FSL RapidIO probing on MDS boards FSL RapidIO won't probe without a proper compatible entry. This patch fixes the issue by adding fsl,rapidio-delta compatible to mpc85xx_ids. Signed-off-by: Randy Vinson <rvinson@mvista.com> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 77f90b3563568..60ed9c067b1d5 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -285,6 +285,7 @@ static struct of_device_id mpc85xx_ids[] = { { .type = "qe", }, { .compatible = "fsl,qe", }, { .compatible = "gianfar", }, + { .compatible = "fsl,rapidio-delta", }, {}, }; -- GitLab From cb1ffb6204712b04396ae0a9f3d1bf93cd8df8fb Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Fri, 19 Jun 2009 03:30:42 -0500 Subject: [PATCH 0076/1002] powerpc/85xx: Fix issue found by lockdep trace in smp_85xx_kick_cpu lockdep trace found the following: ------------[ cut here ]------------ Badness at c007baf0 [verbose debug info unavailable] NIP: c007baf0 LR: c007bad8 CTR: 00000000 REGS: ef855e00 TRAP: 0700 Tainted: G W (2.6.30-06736-g12a31df-dirty) MSR: 00021000 <ME,CE> CR: 24044022 XER: 20000000 TASK = ef858000[1] 'swapper' THREAD: ef854000 CPU: 0 GPR00: 00000000 ef855eb0 ef858000 00000001 000000d0 f1000000 ffbc8000 ffffffff GPR08: 000000d0 c0760000 c0710000 00000007 2fffffff 1004a388 7ffd9400 00000000 GPR16: 00000000 7ffcd100 7ffcd100 7ffcd100 c059cd78 c075c498 c057da7c ffffffff GPR24: ffbc8000 f1000000 00000001 c00bf8b0 c07595d4 000000d0 00021000 000000d0 NIP [c007baf0] lockdep_trace_alloc+0xc0/0xf0 LR [c007bad8] lockdep_trace_alloc+0xa8/0xf0 Call Trace: [ef855eb0] [c007ba60] lockdep_trace_alloc+0x30/0xf0 (unreliable) [ef855ec0] [c00cb3ac] kmem_cache_alloc+0x2c/0xf0 [ef855ee0] [c00bf8b0] __get_vm_area_node+0x80/0x1c0 [ef855f10] [c0017580] __ioremap_caller+0x1d0/0x1e0 [ef855f40] [c057da7c] smp_85xx_kick_cpu+0x64/0x124 [ef855f60] [c0599180] __cpu_up+0xd0/0x1a4 [ef855f80] [c05997c4] cpu_up+0x14c/0x1e0 [ef855fc0] [c05732a0] kernel_init+0x100/0x1c4 [ef855ff0] [c0011524] kernel_thread+0x4c/0x68 Instruction dump: 8009c174 2f800000 409e0048 73c08000 40820040 4818980d 2f830000 419effa0 3d20c076 8009c388 2f800000 409eff90 <0fe00000> 4bffff88 60000000 60000000 We were calling ioremap after we local_irq_restore(flags). A simple reorder fixes the problem. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/platforms/85xx/smp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index cc0b0db8a6f31..62c592ede641c 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -52,20 +52,19 @@ smp_85xx_kick_cpu(int nr) pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); - local_irq_save(flags); - np = of_get_cpu_node(nr, NULL); cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); if (cpu_rel_addr == NULL) { printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); - local_irq_restore(flags); return; } /* Map the spin table */ bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY); + local_irq_save(flags); + out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); @@ -73,10 +72,10 @@ smp_85xx_kick_cpu(int nr) while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) mdelay(1); - iounmap(bptr_vaddr); - local_irq_restore(flags); + iounmap(bptr_vaddr); + pr_debug("waited %d msecs for CPU #%d.\n", n, nr); } -- GitLab From b053dc5a722eade28514f2cc922caf7a4baad987 Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Fri, 19 Jun 2009 08:31:05 -0500 Subject: [PATCH 0077/1002] powerpc: Refactor device tree binding Split device tree binding out of booting-without-of.txt and put them into their own files per binding. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- Documentation/powerpc/booting-without-of.txt | 1168 +---------------- .../powerpc/dts-bindings/4xx/emac.txt | 148 +++ .../powerpc/dts-bindings/gpio/gpio.txt | 50 + .../powerpc/dts-bindings/gpio/mdio.txt | 19 + .../powerpc/dts-bindings/marvell.txt | 521 ++++++++ Documentation/powerpc/dts-bindings/phy.txt | 25 + .../powerpc/dts-bindings/spi-bus.txt | 57 + .../powerpc/dts-bindings/usb-ehci.txt | 25 + Documentation/powerpc/dts-bindings/xilinx.txt | 295 +++++ 9 files changed, 1142 insertions(+), 1166 deletions(-) create mode 100644 Documentation/powerpc/dts-bindings/4xx/emac.txt create mode 100644 Documentation/powerpc/dts-bindings/gpio/gpio.txt create mode 100644 Documentation/powerpc/dts-bindings/gpio/mdio.txt create mode 100644 Documentation/powerpc/dts-bindings/marvell.txt create mode 100644 Documentation/powerpc/dts-bindings/phy.txt create mode 100644 Documentation/powerpc/dts-bindings/spi-bus.txt create mode 100644 Documentation/powerpc/dts-bindings/usb-ehci.txt create mode 100644 Documentation/powerpc/dts-bindings/xilinx.txt diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 8d999d862d0e6..79f533f38c611 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -1238,1122 +1238,7 @@ descriptions for the SOC devices for which new nodes have been defined; this list will expand as more and more SOC-containing platforms are moved over to use the flattened-device-tree model. - a) PHY nodes - - Required properties: - - - device_type : Should be "ethernet-phy" - - interrupts : <a b> where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - reg : The ID number for the phy, usually a small integer - - linux,phandle : phandle for this node; likely referenced by an - ethernet controller node. - - - Example: - - ethernet-phy@0 { - linux,phandle = <2452000> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <0>; - device_type = "ethernet-phy"; - }; - - - b) Interrupt controllers - - Some SOC devices contain interrupt controllers that are different - from the standard Open PIC specification. The SOC device nodes for - these types of controllers should be specified just like a standard - OpenPIC controller. Sense and level information should be encoded - as specified in section 2) of this chapter for each device that - specifies an interrupt. - - Example : - - pic@40000 { - linux,phandle = <40000>; - interrupt-controller; - #address-cells = <0>; - reg = <40000 40000>; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - }; - - c) 4xx/Axon EMAC ethernet nodes - - The EMAC ethernet controller in IBM and AMCC 4xx chips, and also - the Axon bridge. To operate this needs to interact with a ths - special McMAL DMA controller, and sometimes an RGMII or ZMII - interface. In addition to the nodes and properties described - below, the node for the OPB bus on which the EMAC sits must have a - correct clock-frequency property. - - i) The EMAC node itself - - Required properties: - - device_type : "network" - - - compatible : compatible list, contains 2 entries, first is - "ibm,emac-CHIP" where CHIP is the host ASIC (440gx, - 405gp, Axon) and second is either "ibm,emac" or - "ibm,emac4". For Axon, thus, we have: "ibm,emac-axon", - "ibm,emac4" - - interrupts : <interrupt mapping for EMAC IRQ and WOL IRQ> - - interrupt-parent : optional, if needed for interrupt mapping - - reg : <registers mapping> - - local-mac-address : 6 bytes, MAC address - - mal-device : phandle of the associated McMAL node - - mal-tx-channel : 1 cell, index of the tx channel on McMAL associated - with this EMAC - - mal-rx-channel : 1 cell, index of the rx channel on McMAL associated - with this EMAC - - cell-index : 1 cell, hardware index of the EMAC cell on a given - ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on - each Axon chip) - - max-frame-size : 1 cell, maximum frame size supported in bytes - - rx-fifo-size : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec - operations. - For Axon, 2048 - - tx-fifo-size : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec - operations. - For Axon, 2048. - - fifo-entry-size : 1 cell, size of a fifo entry (used to calculate - thresholds). - For Axon, 0x00000010 - - mal-burst-size : 1 cell, MAL burst size (used to calculate thresholds) - in bytes. - For Axon, 0x00000100 (I think ...) - - phy-mode : string, mode of operations of the PHY interface. - Supported values are: "mii", "rmii", "smii", "rgmii", - "tbi", "gmii", rtbi", "sgmii". - For Axon on CAB, it is "rgmii" - - mdio-device : 1 cell, required iff using shared MDIO registers - (440EP). phandle of the EMAC to use to drive the - MDIO lines for the PHY used by this EMAC. - - zmii-device : 1 cell, required iff connected to a ZMII. phandle of - the ZMII device node - - zmii-channel : 1 cell, required iff connected to a ZMII. Which ZMII - channel or 0xffffffff if ZMII is only used for MDIO. - - rgmii-device : 1 cell, required iff connected to an RGMII. phandle - of the RGMII device node. - For Axon: phandle of plb5/plb4/opb/rgmii - - rgmii-channel : 1 cell, required iff connected to an RGMII. Which - RGMII channel is used by this EMAC. - Fox Axon: present, whatever value is appropriate for each - EMAC, that is the content of the current (bogus) "phy-port" - property. - - Optional properties: - - phy-address : 1 cell, optional, MDIO address of the PHY. If absent, - a search is performed. - - phy-map : 1 cell, optional, bitmap of addresses to probe the PHY - for, used if phy-address is absent. bit 0x00000001 is - MDIO address 0. - For Axon it can be absent, though my current driver - doesn't handle phy-address yet so for now, keep - 0x00ffffff in it. - - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec - operations (if absent the value is the same as - rx-fifo-size). For Axon, either absent or 2048. - - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec - operations (if absent the value is the same as - tx-fifo-size). For Axon, either absent or 2048. - - tah-device : 1 cell, optional. If connected to a TAH engine for - offload, phandle of the TAH device node. - - tah-channel : 1 cell, optional. If appropriate, channel used on the - TAH engine. - - Example: - - EMAC0: ethernet@40000800 { - device_type = "network"; - compatible = "ibm,emac-440gp", "ibm,emac"; - interrupt-parent = <&UIC1>; - interrupts = <1c 4 1d 4>; - reg = <40000800 70>; - local-mac-address = [00 04 AC E3 1B 1E]; - mal-device = <&MAL0>; - mal-tx-channel = <0 1>; - mal-rx-channel = <0>; - cell-index = <0>; - max-frame-size = <5dc>; - rx-fifo-size = <1000>; - tx-fifo-size = <800>; - phy-mode = "rmii"; - phy-map = <00000001>; - zmii-device = <&ZMII0>; - zmii-channel = <0>; - }; - - ii) McMAL node - - Required properties: - - device_type : "dma-controller" - - compatible : compatible list, containing 2 entries, first is - "ibm,mcmal-CHIP" where CHIP is the host ASIC (like - emac) and the second is either "ibm,mcmal" or - "ibm,mcmal2". - For Axon, "ibm,mcmal-axon","ibm,mcmal2" - - interrupts : <interrupt mapping for the MAL interrupts sources: - 5 sources: tx_eob, rx_eob, serr, txde, rxde>. - For Axon: This is _different_ from the current - firmware. We use the "delayed" interrupts for txeob - and rxeob. Thus we end up with mapping those 5 MPIC - interrupts, all level positive sensitive: 10, 11, 32, - 33, 34 (in decimal) - - dcr-reg : < DCR registers range > - - dcr-parent : if needed for dcr-reg - - num-tx-chans : 1 cell, number of Tx channels - - num-rx-chans : 1 cell, number of Rx channels - - iii) ZMII node - - Required properties: - - compatible : compatible list, containing 2 entries, first is - "ibm,zmii-CHIP" where CHIP is the host ASIC (like - EMAC) and the second is "ibm,zmii". - For Axon, there is no ZMII node. - - reg : <registers mapping> - - iv) RGMII node - - Required properties: - - compatible : compatible list, containing 2 entries, first is - "ibm,rgmii-CHIP" where CHIP is the host ASIC (like - EMAC) and the second is "ibm,rgmii". - For Axon, "ibm,rgmii-axon","ibm,rgmii" - - reg : <registers mapping> - - revision : as provided by the RGMII new version register if - available. - For Axon: 0x0000012a - - d) Xilinx IP cores - - The Xilinx EDK toolchain ships with a set of IP cores (devices) for use - in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range - of standard device types (network, serial, etc.) and miscellaneous - devices (gpio, LCD, spi, etc). Also, since these devices are - implemented within the fpga fabric every instance of the device can be - synthesised with different options that change the behaviour. - - Each IP-core has a set of parameters which the FPGA designer can use to - control how the core is synthesized. Historically, the EDK tool would - extract the device parameters relevant to device drivers and copy them - into an 'xparameters.h' in the form of #define symbols. This tells the - device drivers how the IP cores are configured, but it requres the kernel - to be recompiled every time the FPGA bitstream is resynthesized. - - The new approach is to export the parameters into the device tree and - generate a new device tree each time the FPGA bitstream changes. The - parameters which used to be exported as #defines will now become - properties of the device node. In general, device nodes for IP-cores - will take the following form: - - (name): (generic-name)@(base-address) { - compatible = "xlnx,(ip-core-name)-(HW_VER)" - [, (list of compatible devices), ...]; - reg = <(baseaddr) (size)>; - interrupt-parent = <&interrupt-controller-phandle>; - interrupts = < ... >; - xlnx,(parameter1) = "(string-value)"; - xlnx,(parameter2) = <(int-value)>; - }; - - (generic-name): an open firmware-style name that describes the - generic class of device. Preferably, this is one word, such - as 'serial' or 'ethernet'. - (ip-core-name): the name of the ip block (given after the BEGIN - directive in system.mhs). Should be in lowercase - and all underscores '_' converted to dashes '-'. - (name): is derived from the "PARAMETER INSTANCE" value. - (parameter#): C_* parameters from system.mhs. The C_ prefix is - dropped from the parameter name, the name is converted - to lowercase and all underscore '_' characters are - converted to dashes '-'. - (baseaddr): the baseaddr parameter value (often named C_BASEADDR). - (HW_VER): from the HW_VER parameter. - (size): the address range size (often C_HIGHADDR - C_BASEADDR + 1). - - Typically, the compatible list will include the exact IP core version - followed by an older IP core version which implements the same - interface or any other device with the same interface. - - 'reg', 'interrupt-parent' and 'interrupts' are all optional properties. - - For example, the following block from system.mhs: - - BEGIN opb_uartlite - PARAMETER INSTANCE = opb_uartlite_0 - PARAMETER HW_VER = 1.00.b - PARAMETER C_BAUDRATE = 115200 - PARAMETER C_DATA_BITS = 8 - PARAMETER C_ODD_PARITY = 0 - PARAMETER C_USE_PARITY = 0 - PARAMETER C_CLK_FREQ = 50000000 - PARAMETER C_BASEADDR = 0xEC100000 - PARAMETER C_HIGHADDR = 0xEC10FFFF - BUS_INTERFACE SOPB = opb_7 - PORT OPB_Clk = CLK_50MHz - PORT Interrupt = opb_uartlite_0_Interrupt - PORT RX = opb_uartlite_0_RX - PORT TX = opb_uartlite_0_TX - PORT OPB_Rst = sys_bus_reset_0 - END - - becomes the following device tree node: - - opb_uartlite_0: serial@ec100000 { - device_type = "serial"; - compatible = "xlnx,opb-uartlite-1.00.b"; - reg = <ec100000 10000>; - interrupt-parent = <&opb_intc_0>; - interrupts = <1 0>; // got this from the opb_intc parameters - current-speed = <d#115200>; // standard serial device prop - clock-frequency = <d#50000000>; // standard serial device prop - xlnx,data-bits = <8>; - xlnx,odd-parity = <0>; - xlnx,use-parity = <0>; - }; - - Some IP cores actually implement 2 or more logical devices. In - this case, the device should still describe the whole IP core with - a single node and add a child node for each logical device. The - ranges property can be used to translate from parent IP-core to the - registers of each device. In addition, the parent node should be - compatible with the bus type 'xlnx,compound', and should contain - #address-cells and #size-cells, as with any other bus. (Note: this - makes the assumption that both logical devices have the same bus - binding. If this is not true, then separate nodes should be used - for each logical device). The 'cell-index' property can be used to - enumerate logical devices within an IP core. For example, the - following is the system.mhs entry for the dual ps2 controller found - on the ml403 reference design. - - BEGIN opb_ps2_dual_ref - PARAMETER INSTANCE = opb_ps2_dual_ref_0 - PARAMETER HW_VER = 1.00.a - PARAMETER C_BASEADDR = 0xA9000000 - PARAMETER C_HIGHADDR = 0xA9001FFF - BUS_INTERFACE SOPB = opb_v20_0 - PORT Sys_Intr1 = ps2_1_intr - PORT Sys_Intr2 = ps2_2_intr - PORT Clkin1 = ps2_clk_rx_1 - PORT Clkin2 = ps2_clk_rx_2 - PORT Clkpd1 = ps2_clk_tx_1 - PORT Clkpd2 = ps2_clk_tx_2 - PORT Rx1 = ps2_d_rx_1 - PORT Rx2 = ps2_d_rx_2 - PORT Txpd1 = ps2_d_tx_1 - PORT Txpd2 = ps2_d_tx_2 - END - - It would result in the following device tree nodes: - - opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "xlnx,compound"; - ranges = <0 a9000000 2000>; - // If this device had extra parameters, then they would - // go here. - ps2@0 { - compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; - reg = <0 40>; - interrupt-parent = <&opb_intc_0>; - interrupts = <3 0>; - cell-index = <0>; - }; - ps2@1000 { - compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; - reg = <1000 40>; - interrupt-parent = <&opb_intc_0>; - interrupts = <3 0>; - cell-index = <0>; - }; - }; - - Also, the system.mhs file defines bus attachments from the processor - to the devices. The device tree structure should reflect the bus - attachments. Again an example; this system.mhs fragment: - - BEGIN ppc405_virtex4 - PARAMETER INSTANCE = ppc405_0 - PARAMETER HW_VER = 1.01.a - BUS_INTERFACE DPLB = plb_v34_0 - BUS_INTERFACE IPLB = plb_v34_0 - END - - BEGIN opb_intc - PARAMETER INSTANCE = opb_intc_0 - PARAMETER HW_VER = 1.00.c - PARAMETER C_BASEADDR = 0xD1000FC0 - PARAMETER C_HIGHADDR = 0xD1000FDF - BUS_INTERFACE SOPB = opb_v20_0 - END - - BEGIN opb_uart16550 - PARAMETER INSTANCE = opb_uart16550_0 - PARAMETER HW_VER = 1.00.d - PARAMETER C_BASEADDR = 0xa0000000 - PARAMETER C_HIGHADDR = 0xa0001FFF - BUS_INTERFACE SOPB = opb_v20_0 - END - - BEGIN plb_v34 - PARAMETER INSTANCE = plb_v34_0 - PARAMETER HW_VER = 1.02.a - END - - BEGIN plb_bram_if_cntlr - PARAMETER INSTANCE = plb_bram_if_cntlr_0 - PARAMETER HW_VER = 1.00.b - PARAMETER C_BASEADDR = 0xFFFF0000 - PARAMETER C_HIGHADDR = 0xFFFFFFFF - BUS_INTERFACE SPLB = plb_v34_0 - END - - BEGIN plb2opb_bridge - PARAMETER INSTANCE = plb2opb_bridge_0 - PARAMETER HW_VER = 1.01.a - PARAMETER C_RNG0_BASEADDR = 0x20000000 - PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF - PARAMETER C_RNG1_BASEADDR = 0x60000000 - PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF - PARAMETER C_RNG2_BASEADDR = 0x80000000 - PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF - PARAMETER C_RNG3_BASEADDR = 0xC0000000 - PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF - BUS_INTERFACE SPLB = plb_v34_0 - BUS_INTERFACE MOPB = opb_v20_0 - END - - Gives this device tree (some properties removed for clarity): - - plb@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "xlnx,plb-v34-1.02.a"; - device_type = "ibm,plb"; - ranges; // 1:1 translation - - plb_bram_if_cntrl_0: bram@ffff0000 { - reg = <ffff0000 10000>; - } - - opb@20000000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <20000000 20000000 20000000 - 60000000 60000000 20000000 - 80000000 80000000 40000000 - c0000000 c0000000 20000000>; - - opb_uart16550_0: serial@a0000000 { - reg = <a00000000 2000>; - }; - - opb_intc_0: interrupt-controller@d1000fc0 { - reg = <d1000fc0 20>; - }; - }; - }; - - That covers the general approach to binding xilinx IP cores into the - device tree. The following are bindings for specific devices: - - i) Xilinx ML300 Framebuffer - - Simple framebuffer device from the ML300 reference design (also on the - ML403 reference design as well as others). - - Optional properties: - - resolution = <xres yres> : pixel resolution of framebuffer. Some - implementations use a different resolution. - Default is <d#640 d#480> - - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory. - Default is <d#1024 d#480>. - - rotate-display (empty) : rotate display 180 degrees. - - ii) Xilinx SystemACE - - The Xilinx SystemACE device is used to program FPGAs from an FPGA - bitstream stored on a CF card. It can also be used as a generic CF - interface device. - - Optional properties: - - 8-bit (empty) : Set this property for SystemACE in 8 bit mode - - iii) Xilinx EMAC and Xilinx TEMAC - - Xilinx Ethernet devices. In addition to general xilinx properties - listed above, nodes for these devices should include a phy-handle - property, and may include other common network device properties - like local-mac-address. - - iv) Xilinx Uartlite - - Xilinx uartlite devices are simple fixed speed serial ports. - - Required properties: - - current-speed : Baud rate of uartlite - - v) Xilinx hwicap - - Xilinx hwicap devices provide access to the configuration logic - of the FPGA through the Internal Configuration Access Port - (ICAP). The ICAP enables partial reconfiguration of the FPGA, - readback of the configuration information, and some control over - 'warm boots' of the FPGA fabric. - - Required properties: - - xlnx,family : The family of the FPGA, necessary since the - capabilities of the underlying ICAP hardware - differ between different families. May be - 'virtex2p', 'virtex4', or 'virtex5'. - - vi) Xilinx Uart 16550 - - Xilinx UART 16550 devices are very similar to the NS16550 but with - different register spacing and an offset from the base address. - - Required properties: - - clock-frequency : Frequency of the clock input - - reg-offset : A value of 3 is required - - reg-shift : A value of 2 is required - - e) USB EHCI controllers - - Required properties: - - compatible : should be "usb-ehci". - - reg : should contain at least address and length of the standard EHCI - register set for the device. Optional platform-dependent registers - (debug-port or other) can be also specified here, but only after - definition of standard EHCI registers. - - interrupts : one EHCI interrupt should be described here. - If device registers are implemented in big endian mode, the device - node should have "big-endian-regs" property. - If controller implementation operates with big endian descriptors, - "big-endian-desc" property should be specified. - If both big endian registers and descriptors are used by the controller - implementation, "big-endian" property can be specified instead of having - both "big-endian-regs" and "big-endian-desc". - - Example (Sequoia 440EPx): - ehci@e0000300 { - compatible = "ibm,usb-ehci-440epx", "usb-ehci"; - interrupt-parent = <&UIC0>; - interrupts = <1a 4>; - reg = <0 e0000300 90 0 e0000390 70>; - big-endian; - }; - - f) MDIO on GPIOs - - Currently defined compatibles: - - virtual,gpio-mdio - - MDC and MDIO lines connected to GPIO controllers are listed in the - gpios property as described in section VIII.1 in the following order: - - MDC, MDIO. - - Example: - - mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qe_pio_a 11 - &qe_pio_c 6>; - }; - - g) SPI (Serial Peripheral Interface) busses - - SPI busses can be described with a node for the SPI master device - and a set of child nodes for each SPI slave on the bus. For this - discussion, it is assumed that the system's SPI controller is in - SPI master mode. This binding does not describe SPI controllers - in slave mode. - - The SPI master node requires the following properties: - - #address-cells - number of cells required to define a chip select - address on the SPI bus. - - #size-cells - should be zero. - - compatible - name of SPI bus controller following generic names - recommended practice. - No other properties are required in the SPI bus node. It is assumed - that a driver for an SPI bus device will understand that it is an SPI bus. - However, the binding does not attempt to define the specific method for - assigning chip select numbers. Since SPI chip select configuration is - flexible and non-standardized, it is left out of this binding with the - assumption that board specific platform code will be used to manage - chip selects. Individual drivers can define additional properties to - support describing the chip select layout. - - SPI slave nodes must be children of the SPI master node and can - contain the following properties. - - reg - (required) chip select address of device. - - compatible - (required) name of SPI device following generic names - recommended practice - - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz - - spi-cpol - (optional) Empty property indicating device requires - inverse clock polarity (CPOL) mode - - spi-cpha - (optional) Empty property indicating device requires - shifted clock phase (CPHA) mode - - spi-cs-high - (optional) Empty property indicating device requires - chip select active high - - SPI example for an MPC5200 SPI bus: - spi@f00 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi"; - reg = <0xf00 0x20>; - interrupts = <2 13 0 2 14 0>; - interrupt-parent = <&mpc5200_pic>; - - ethernet-switch@0 { - compatible = "micrel,ks8995m"; - spi-max-frequency = <1000000>; - reg = <0>; - }; - - codec@1 { - compatible = "ti,tlv320aic26"; - spi-max-frequency = <100000>; - reg = <1>; - }; - }; - -VII - Marvell Discovery mv64[345]6x System Controller chips -=========================================================== - -The Marvell mv64[345]60 series of system controller chips contain -many of the peripherals needed to implement a complete computer -system. In this section, we define device tree nodes to describe -the system controller chip itself and each of the peripherals -which it contains. Compatible string values for each node are -prefixed with the string "marvell,", for Marvell Technology Group Ltd. - -1) The /system-controller node - - This node is used to represent the system-controller and must be - present when the system uses a system controller chip. The top-level - system-controller node contains information that is global to all - devices within the system controller chip. The node name begins - with "system-controller" followed by the unit address, which is - the base address of the memory-mapped register set for the system - controller chip. - - Required properties: - - - ranges : Describes the translation of system controller addresses - for memory mapped registers. - - clock-frequency: Contains the main clock frequency for the system - controller chip. - - reg : This property defines the address and size of the - memory-mapped registers contained within the system controller - chip. The address specified in the "reg" property should match - the unit address of the system-controller node. - - #address-cells : Address representation for system controller - devices. This field represents the number of cells needed to - represent the address of the memory-mapped registers of devices - within the system controller chip. - - #size-cells : Size representation for for the memory-mapped - registers within the system controller chip. - - #interrupt-cells : Defines the width of cells used to represent - interrupts. - - Optional properties: - - - model : The specific model of the system controller chip. Such - as, "mv64360", "mv64460", or "mv64560". - - compatible : A string identifying the compatibility identifiers - of the system controller chip. - - The system-controller node contains child nodes for each system - controller device that the platform uses. Nodes should not be created - for devices which exist on the system controller chip but are not used - - Example Marvell Discovery mv64360 system-controller node: - - system-controller@f1000000 { /* Marvell Discovery mv64360 */ - #address-cells = <1>; - #size-cells = <1>; - model = "mv64360"; /* Default */ - compatible = "marvell,mv64360"; - clock-frequency = <133333333>; - reg = <0xf1000000 0x10000>; - virtual-reg = <0xf1000000>; - ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ - 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ - 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ - 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ - 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ - - [ child node definitions... ] - } - -2) Child nodes of /system-controller - - a) Marvell Discovery MDIO bus - - The MDIO is a bus to which the PHY devices are connected. For each - device that exists on this bus, a child node should be created. See - the definition of the PHY node below for an example of how to define - a PHY. - - Required properties: - - #address-cells : Should be <1> - - #size-cells : Should be <0> - - device_type : Should be "mdio" - - compatible : Should be "marvell,mv64360-mdio" - - Example: - - mdio { - #address-cells = <1>; - #size-cells = <0>; - device_type = "mdio"; - compatible = "marvell,mv64360-mdio"; - - ethernet-phy@0 { - ...... - }; - }; - - - b) Marvell Discovery ethernet controller - - The Discover ethernet controller is described with two levels - of nodes. The first level describes an ethernet silicon block - and the second level describes up to 3 ethernet nodes within - that block. The reason for the multiple levels is that the - registers for the node are interleaved within a single set - of registers. The "ethernet-block" level describes the - shared register set, and the "ethernet" nodes describe ethernet - port-specific properties. - - Ethernet block node - - Required properties: - - #address-cells : <1> - - #size-cells : <0> - - compatible : "marvell,mv64360-eth-block" - - reg : Offset and length of the register set for this block - - Example Discovery Ethernet block node: - ethernet-block@2000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "marvell,mv64360-eth-block"; - reg = <0x2000 0x2000>; - ethernet@0 { - ....... - }; - }; - - Ethernet port node - - Required properties: - - device_type : Should be "network". - - compatible : Should be "marvell,mv64360-eth". - - reg : Should be <0>, <1>, or <2>, according to which registers - within the silicon block the device uses. - - interrupts : <a> where a is the interrupt number for the port. - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - phy : the phandle for the PHY connected to this ethernet - controller. - - local-mac-address : 6 bytes, MAC address - - Example Discovery Ethernet port node: - ethernet@0 { - device_type = "network"; - compatible = "marvell,mv64360-eth"; - reg = <0>; - interrupts = <32>; - interrupt-parent = <&PIC>; - phy = <&PHY0>; - local-mac-address = [ 00 00 00 00 00 00 ]; - }; - - - - c) Marvell Discovery PHY nodes - - Required properties: - - device_type : Should be "ethernet-phy" - - interrupts : <a> where a is the interrupt number for this phy. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - reg : The ID number for the phy, usually a small integer - - Example Discovery PHY node: - ethernet-phy@1 { - device_type = "ethernet-phy"; - compatible = "broadcom,bcm5421"; - interrupts = <76>; /* GPP 12 */ - interrupt-parent = <&PIC>; - reg = <1>; - }; - - - d) Marvell Discovery SDMA nodes - - Represent DMA hardware associated with the MPSC (multiprotocol - serial controllers). - - Required properties: - - compatible : "marvell,mv64360-sdma" - - reg : Offset and length of the register set for this device - - interrupts : <a> where a is the interrupt number for the DMA - device. - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery SDMA node: - sdma@4000 { - compatible = "marvell,mv64360-sdma"; - reg = <0x4000 0xc18>; - virtual-reg = <0xf1004000>; - interrupts = <36>; - interrupt-parent = <&PIC>; - }; - - - e) Marvell Discovery BRG nodes - - Represent baud rate generator hardware associated with the MPSC - (multiprotocol serial controllers). - - Required properties: - - compatible : "marvell,mv64360-brg" - - reg : Offset and length of the register set for this device - - clock-src : A value from 0 to 15 which selects the clock - source for the baud rate generator. This value corresponds - to the CLKS value in the BRGx configuration register. See - the mv64x60 User's Manual. - - clock-frequence : The frequency (in Hz) of the baud rate - generator's input clock. - - current-speed : The current speed setting (presumably by - firmware) of the baud rate generator. - - Example Discovery BRG node: - brg@b200 { - compatible = "marvell,mv64360-brg"; - reg = <0xb200 0x8>; - clock-src = <8>; - clock-frequency = <133333333>; - current-speed = <9600>; - }; - - - f) Marvell Discovery CUNIT nodes - - Represent the Serial Communications Unit device hardware. - - Required properties: - - reg : Offset and length of the register set for this device - - Example Discovery CUNIT node: - cunit@f200 { - reg = <0xf200 0x200>; - }; - - - g) Marvell Discovery MPSCROUTING nodes - - Represent the Discovery's MPSC routing hardware - - Required properties: - - reg : Offset and length of the register set for this device - - Example Discovery CUNIT node: - mpscrouting@b500 { - reg = <0xb400 0xc>; - }; - - - h) Marvell Discovery MPSCINTR nodes - - Represent the Discovery's MPSC DMA interrupt hardware registers - (SDMA cause and mask registers). - - Required properties: - - reg : Offset and length of the register set for this device - - Example Discovery MPSCINTR node: - mpsintr@b800 { - reg = <0xb800 0x100>; - }; - - - i) Marvell Discovery MPSC nodes - - Represent the Discovery's MPSC (Multiprotocol Serial Controller) - serial port. - - Required properties: - - device_type : "serial" - - compatible : "marvell,mv64360-mpsc" - - reg : Offset and length of the register set for this device - - sdma : the phandle for the SDMA node used by this port - - brg : the phandle for the BRG node used by this port - - cunit : the phandle for the CUNIT node used by this port - - mpscrouting : the phandle for the MPSCROUTING node used by this port - - mpscintr : the phandle for the MPSCINTR node used by this port - - cell-index : the hardware index of this cell in the MPSC core - - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) - register - - interrupts : <a> where a is the interrupt number for the MPSC. - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery MPSCINTR node: - mpsc@8000 { - device_type = "serial"; - compatible = "marvell,mv64360-mpsc"; - reg = <0x8000 0x38>; - virtual-reg = <0xf1008000>; - sdma = <&SDMA0>; - brg = <&BRG0>; - cunit = <&CUNIT>; - mpscrouting = <&MPSCROUTING>; - mpscintr = <&MPSCINTR>; - cell-index = <0>; - max_idle = <40>; - interrupts = <40>; - interrupt-parent = <&PIC>; - }; - - - j) Marvell Discovery Watch Dog Timer nodes - - Represent the Discovery's watchdog timer hardware - - Required properties: - - compatible : "marvell,mv64360-wdt" - - reg : Offset and length of the register set for this device - - Example Discovery Watch Dog Timer node: - wdt@b410 { - compatible = "marvell,mv64360-wdt"; - reg = <0xb410 0x8>; - }; - - - k) Marvell Discovery I2C nodes - - Represent the Discovery's I2C hardware - - Required properties: - - device_type : "i2c" - - compatible : "marvell,mv64360-i2c" - - reg : Offset and length of the register set for this device - - interrupts : <a> where a is the interrupt number for the I2C. - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery I2C node: - compatible = "marvell,mv64360-i2c"; - reg = <0xc000 0x20>; - virtual-reg = <0xf100c000>; - interrupts = <37>; - interrupt-parent = <&PIC>; - }; - - - l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes - - Represent the Discovery's PIC hardware - - Required properties: - - #interrupt-cells : <1> - - #address-cells : <0> - - compatible : "marvell,mv64360-pic" - - reg : Offset and length of the register set for this device - - interrupt-controller - - Example Discovery PIC node: - pic { - #interrupt-cells = <1>; - #address-cells = <0>; - compatible = "marvell,mv64360-pic"; - reg = <0x0 0x88>; - interrupt-controller; - }; - - - m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes - - Represent the Discovery's MPP hardware - - Required properties: - - compatible : "marvell,mv64360-mpp" - - reg : Offset and length of the register set for this device - - Example Discovery MPP node: - mpp@f000 { - compatible = "marvell,mv64360-mpp"; - reg = <0xf000 0x10>; - }; - - - n) Marvell Discovery GPP (General Purpose Pins) nodes - - Represent the Discovery's GPP hardware - - Required properties: - - compatible : "marvell,mv64360-gpp" - - reg : Offset and length of the register set for this device - - Example Discovery GPP node: - gpp@f000 { - compatible = "marvell,mv64360-gpp"; - reg = <0xf100 0x20>; - }; - - - o) Marvell Discovery PCI host bridge node - - Represents the Discovery's PCI host bridge device. The properties - for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE - 1275-1994. A typical value for the compatible property is - "marvell,mv64360-pci". - - Example Discovery PCI host bridge node - pci@80000000 { - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - device_type = "pci"; - compatible = "marvell,mv64360-pci"; - reg = <0xcf8 0x8>; - ranges = <0x01000000 0x0 0x0 - 0x88000000 0x0 0x01000000 - 0x02000000 0x0 0x80000000 - 0x80000000 0x0 0x08000000>; - bus-range = <0 255>; - clock-frequency = <66000000>; - interrupt-parent = <&PIC>; - interrupt-map-mask = <0xf800 0x0 0x0 0x7>; - interrupt-map = < - /* IDSEL 0x0a */ - 0x5000 0 0 1 &PIC 80 - 0x5000 0 0 2 &PIC 81 - 0x5000 0 0 3 &PIC 91 - 0x5000 0 0 4 &PIC 93 - - /* IDSEL 0x0b */ - 0x5800 0 0 1 &PIC 91 - 0x5800 0 0 2 &PIC 93 - 0x5800 0 0 3 &PIC 80 - 0x5800 0 0 4 &PIC 81 - - /* IDSEL 0x0c */ - 0x6000 0 0 1 &PIC 91 - 0x6000 0 0 2 &PIC 93 - 0x6000 0 0 3 &PIC 80 - 0x6000 0 0 4 &PIC 81 - - /* IDSEL 0x0d */ - 0x6800 0 0 1 &PIC 93 - 0x6800 0 0 2 &PIC 80 - 0x6800 0 0 3 &PIC 81 - 0x6800 0 0 4 &PIC 91 - >; - }; - - - p) Marvell Discovery CPU Error nodes - - Represent the Discovery's CPU error handler device. - - Required properties: - - compatible : "marvell,mv64360-cpu-error" - - reg : Offset and length of the register set for this device - - interrupts : the interrupt number for this device - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery CPU Error node: - cpu-error@0070 { - compatible = "marvell,mv64360-cpu-error"; - reg = <0x70 0x10 0x128 0x28>; - interrupts = <3>; - interrupt-parent = <&PIC>; - }; - - - q) Marvell Discovery SRAM Controller nodes - - Represent the Discovery's SRAM controller device. - - Required properties: - - compatible : "marvell,mv64360-sram-ctrl" - - reg : Offset and length of the register set for this device - - interrupts : the interrupt number for this device - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery SRAM Controller node: - sram-ctrl@0380 { - compatible = "marvell,mv64360-sram-ctrl"; - reg = <0x380 0x80>; - interrupts = <13>; - interrupt-parent = <&PIC>; - }; - - - r) Marvell Discovery PCI Error Handler nodes - - Represent the Discovery's PCI error handler device. - - Required properties: - - compatible : "marvell,mv64360-pci-error" - - reg : Offset and length of the register set for this device - - interrupts : the interrupt number for this device - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery PCI Error Handler node: - pci-error@1d40 { - compatible = "marvell,mv64360-pci-error"; - reg = <0x1d40 0x40 0xc28 0x4>; - interrupts = <12>; - interrupt-parent = <&PIC>; - }; - - - s) Marvell Discovery Memory Controller nodes - - Represent the Discovery's memory controller device. - - Required properties: - - compatible : "marvell,mv64360-mem-ctrl" - - reg : Offset and length of the register set for this device - - interrupts : the interrupt number for this device - - interrupt-parent : the phandle for the interrupt controller - that services interrupts for this device. - - Example Discovery Memory Controller node: - mem-ctrl@1400 { - compatible = "marvell,mv64360-mem-ctrl"; - reg = <0x1400 0x60>; - interrupts = <17>; - interrupt-parent = <&PIC>; - }; - - -VIII - Specifying interrupt information for devices +VII - Specifying interrupt information for devices =================================================== The device tree represents the busses and devices of a hardware @@ -2439,56 +1324,7 @@ encodings listed below: 2 = high to low edge sensitive type enabled 3 = low to high edge sensitive type enabled -IX - Specifying GPIO information for devices -============================================ - -1) gpios property ------------------ - -Nodes that makes use of GPIOs should define them using `gpios' property, -format of which is: <&gpio-controller1-phandle gpio1-specifier - &gpio-controller2-phandle gpio2-specifier - 0 /* holes are permitted, means no GPIO 3 */ - &gpio-controller4-phandle gpio4-specifier - ...>; - -Note that gpio-specifier length is controller dependent. - -gpio-specifier may encode: bank, pin position inside the bank, -whether pin is open-drain and whether pin is logically inverted. - -Example of the node using GPIOs: - - node { - gpios = <&qe_pio_e 18 0>; - }; - -In this example gpio-specifier is "18 0" and encodes GPIO pin number, -and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. - -2) gpio-controller nodes ------------------------- - -Every GPIO controller node must have #gpio-cells property defined, -this information will be used to translate gpio-specifiers. - -Example of two SOC GPIO banks defined as gpio-controller nodes: - - qe_pio_a: gpio-controller@1400 { - #gpio-cells = <2>; - compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; - reg = <0x1400 0x18>; - gpio-controller; - }; - - qe_pio_e: gpio-controller@1460 { - #gpio-cells = <2>; - compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; - reg = <0x1460 0x18>; - gpio-controller; - }; - -X - Specifying Device Power Management Information (sleep property) +VIII - Specifying Device Power Management Information (sleep property) =================================================================== Devices on SOCs often have mechanisms for placing devices into low-power diff --git a/Documentation/powerpc/dts-bindings/4xx/emac.txt b/Documentation/powerpc/dts-bindings/4xx/emac.txt new file mode 100644 index 0000000000000..2161334a7ca51 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/4xx/emac.txt @@ -0,0 +1,148 @@ + 4xx/Axon EMAC ethernet nodes + + The EMAC ethernet controller in IBM and AMCC 4xx chips, and also + the Axon bridge. To operate this needs to interact with a ths + special McMAL DMA controller, and sometimes an RGMII or ZMII + interface. In addition to the nodes and properties described + below, the node for the OPB bus on which the EMAC sits must have a + correct clock-frequency property. + + i) The EMAC node itself + + Required properties: + - device_type : "network" + + - compatible : compatible list, contains 2 entries, first is + "ibm,emac-CHIP" where CHIP is the host ASIC (440gx, + 405gp, Axon) and second is either "ibm,emac" or + "ibm,emac4". For Axon, thus, we have: "ibm,emac-axon", + "ibm,emac4" + - interrupts : <interrupt mapping for EMAC IRQ and WOL IRQ> + - interrupt-parent : optional, if needed for interrupt mapping + - reg : <registers mapping> + - local-mac-address : 6 bytes, MAC address + - mal-device : phandle of the associated McMAL node + - mal-tx-channel : 1 cell, index of the tx channel on McMAL associated + with this EMAC + - mal-rx-channel : 1 cell, index of the rx channel on McMAL associated + with this EMAC + - cell-index : 1 cell, hardware index of the EMAC cell on a given + ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on + each Axon chip) + - max-frame-size : 1 cell, maximum frame size supported in bytes + - rx-fifo-size : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec + operations. + For Axon, 2048 + - tx-fifo-size : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec + operations. + For Axon, 2048. + - fifo-entry-size : 1 cell, size of a fifo entry (used to calculate + thresholds). + For Axon, 0x00000010 + - mal-burst-size : 1 cell, MAL burst size (used to calculate thresholds) + in bytes. + For Axon, 0x00000100 (I think ...) + - phy-mode : string, mode of operations of the PHY interface. + Supported values are: "mii", "rmii", "smii", "rgmii", + "tbi", "gmii", rtbi", "sgmii". + For Axon on CAB, it is "rgmii" + - mdio-device : 1 cell, required iff using shared MDIO registers + (440EP). phandle of the EMAC to use to drive the + MDIO lines for the PHY used by this EMAC. + - zmii-device : 1 cell, required iff connected to a ZMII. phandle of + the ZMII device node + - zmii-channel : 1 cell, required iff connected to a ZMII. Which ZMII + channel or 0xffffffff if ZMII is only used for MDIO. + - rgmii-device : 1 cell, required iff connected to an RGMII. phandle + of the RGMII device node. + For Axon: phandle of plb5/plb4/opb/rgmii + - rgmii-channel : 1 cell, required iff connected to an RGMII. Which + RGMII channel is used by this EMAC. + Fox Axon: present, whatever value is appropriate for each + EMAC, that is the content of the current (bogus) "phy-port" + property. + + Optional properties: + - phy-address : 1 cell, optional, MDIO address of the PHY. If absent, + a search is performed. + - phy-map : 1 cell, optional, bitmap of addresses to probe the PHY + for, used if phy-address is absent. bit 0x00000001 is + MDIO address 0. + For Axon it can be absent, though my current driver + doesn't handle phy-address yet so for now, keep + 0x00ffffff in it. + - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec + operations (if absent the value is the same as + rx-fifo-size). For Axon, either absent or 2048. + - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec + operations (if absent the value is the same as + tx-fifo-size). For Axon, either absent or 2048. + - tah-device : 1 cell, optional. If connected to a TAH engine for + offload, phandle of the TAH device node. + - tah-channel : 1 cell, optional. If appropriate, channel used on the + TAH engine. + + Example: + + EMAC0: ethernet@40000800 { + device_type = "network"; + compatible = "ibm,emac-440gp", "ibm,emac"; + interrupt-parent = <&UIC1>; + interrupts = <1c 4 1d 4>; + reg = <40000800 70>; + local-mac-address = [00 04 AC E3 1B 1E]; + mal-device = <&MAL0>; + mal-tx-channel = <0 1>; + mal-rx-channel = <0>; + cell-index = <0>; + max-frame-size = <5dc>; + rx-fifo-size = <1000>; + tx-fifo-size = <800>; + phy-mode = "rmii"; + phy-map = <00000001>; + zmii-device = <&ZMII0>; + zmii-channel = <0>; + }; + + ii) McMAL node + + Required properties: + - device_type : "dma-controller" + - compatible : compatible list, containing 2 entries, first is + "ibm,mcmal-CHIP" where CHIP is the host ASIC (like + emac) and the second is either "ibm,mcmal" or + "ibm,mcmal2". + For Axon, "ibm,mcmal-axon","ibm,mcmal2" + - interrupts : <interrupt mapping for the MAL interrupts sources: + 5 sources: tx_eob, rx_eob, serr, txde, rxde>. + For Axon: This is _different_ from the current + firmware. We use the "delayed" interrupts for txeob + and rxeob. Thus we end up with mapping those 5 MPIC + interrupts, all level positive sensitive: 10, 11, 32, + 33, 34 (in decimal) + - dcr-reg : < DCR registers range > + - dcr-parent : if needed for dcr-reg + - num-tx-chans : 1 cell, number of Tx channels + - num-rx-chans : 1 cell, number of Rx channels + + iii) ZMII node + + Required properties: + - compatible : compatible list, containing 2 entries, first is + "ibm,zmii-CHIP" where CHIP is the host ASIC (like + EMAC) and the second is "ibm,zmii". + For Axon, there is no ZMII node. + - reg : <registers mapping> + + iv) RGMII node + + Required properties: + - compatible : compatible list, containing 2 entries, first is + "ibm,rgmii-CHIP" where CHIP is the host ASIC (like + EMAC) and the second is "ibm,rgmii". + For Axon, "ibm,rgmii-axon","ibm,rgmii" + - reg : <registers mapping> + - revision : as provided by the RGMII new version register if + available. + For Axon: 0x0000012a + diff --git a/Documentation/powerpc/dts-bindings/gpio/gpio.txt b/Documentation/powerpc/dts-bindings/gpio/gpio.txt new file mode 100644 index 0000000000000..edaa84d288a16 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/gpio/gpio.txt @@ -0,0 +1,50 @@ +Specifying GPIO information for devices +============================================ + +1) gpios property +----------------- + +Nodes that makes use of GPIOs should define them using `gpios' property, +format of which is: <&gpio-controller1-phandle gpio1-specifier + &gpio-controller2-phandle gpio2-specifier + 0 /* holes are permitted, means no GPIO 3 */ + &gpio-controller4-phandle gpio4-specifier + ...>; + +Note that gpio-specifier length is controller dependent. + +gpio-specifier may encode: bank, pin position inside the bank, +whether pin is open-drain and whether pin is logically inverted. + +Example of the node using GPIOs: + + node { + gpios = <&qe_pio_e 18 0>; + }; + +In this example gpio-specifier is "18 0" and encodes GPIO pin number, +and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. + +2) gpio-controller nodes +------------------------ + +Every GPIO controller node must have #gpio-cells property defined, +this information will be used to translate gpio-specifiers. + +Example of two SOC GPIO banks defined as gpio-controller nodes: + + qe_pio_a: gpio-controller@1400 { + #gpio-cells = <2>; + compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; + reg = <0x1400 0x18>; + gpio-controller; + }; + + qe_pio_e: gpio-controller@1460 { + #gpio-cells = <2>; + compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; + reg = <0x1460 0x18>; + gpio-controller; + }; + + diff --git a/Documentation/powerpc/dts-bindings/gpio/mdio.txt b/Documentation/powerpc/dts-bindings/gpio/mdio.txt new file mode 100644 index 0000000000000..bc95495290147 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/gpio/mdio.txt @@ -0,0 +1,19 @@ +MDIO on GPIOs + +Currently defined compatibles: +- virtual,gpio-mdio + +MDC and MDIO lines connected to GPIO controllers are listed in the +gpios property as described in section VIII.1 in the following order: + +MDC, MDIO. + +Example: + +mdio { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = <&qe_pio_a 11 + &qe_pio_c 6>; +}; diff --git a/Documentation/powerpc/dts-bindings/marvell.txt b/Documentation/powerpc/dts-bindings/marvell.txt new file mode 100644 index 0000000000000..3708a2fd47473 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/marvell.txt @@ -0,0 +1,521 @@ +Marvell Discovery mv64[345]6x System Controller chips +=========================================================== + +The Marvell mv64[345]60 series of system controller chips contain +many of the peripherals needed to implement a complete computer +system. In this section, we define device tree nodes to describe +the system controller chip itself and each of the peripherals +which it contains. Compatible string values for each node are +prefixed with the string "marvell,", for Marvell Technology Group Ltd. + +1) The /system-controller node + + This node is used to represent the system-controller and must be + present when the system uses a system controller chip. The top-level + system-controller node contains information that is global to all + devices within the system controller chip. The node name begins + with "system-controller" followed by the unit address, which is + the base address of the memory-mapped register set for the system + controller chip. + + Required properties: + + - ranges : Describes the translation of system controller addresses + for memory mapped registers. + - clock-frequency: Contains the main clock frequency for the system + controller chip. + - reg : This property defines the address and size of the + memory-mapped registers contained within the system controller + chip. The address specified in the "reg" property should match + the unit address of the system-controller node. + - #address-cells : Address representation for system controller + devices. This field represents the number of cells needed to + represent the address of the memory-mapped registers of devices + within the system controller chip. + - #size-cells : Size representation for for the memory-mapped + registers within the system controller chip. + - #interrupt-cells : Defines the width of cells used to represent + interrupts. + + Optional properties: + + - model : The specific model of the system controller chip. Such + as, "mv64360", "mv64460", or "mv64560". + - compatible : A string identifying the compatibility identifiers + of the system controller chip. + + The system-controller node contains child nodes for each system + controller device that the platform uses. Nodes should not be created + for devices which exist on the system controller chip but are not used + + Example Marvell Discovery mv64360 system-controller node: + + system-controller@f1000000 { /* Marvell Discovery mv64360 */ + #address-cells = <1>; + #size-cells = <1>; + model = "mv64360"; /* Default */ + compatible = "marvell,mv64360"; + clock-frequency = <133333333>; + reg = <0xf1000000 0x10000>; + virtual-reg = <0xf1000000>; + ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ + 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ + 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ + 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ + 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ + + [ child node definitions... ] + } + +2) Child nodes of /system-controller + + a) Marvell Discovery MDIO bus + + The MDIO is a bus to which the PHY devices are connected. For each + device that exists on this bus, a child node should be created. See + the definition of the PHY node below for an example of how to define + a PHY. + + Required properties: + - #address-cells : Should be <1> + - #size-cells : Should be <0> + - device_type : Should be "mdio" + - compatible : Should be "marvell,mv64360-mdio" + + Example: + + mdio { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "marvell,mv64360-mdio"; + + ethernet-phy@0 { + ...... + }; + }; + + + b) Marvell Discovery ethernet controller + + The Discover ethernet controller is described with two levels + of nodes. The first level describes an ethernet silicon block + and the second level describes up to 3 ethernet nodes within + that block. The reason for the multiple levels is that the + registers for the node are interleaved within a single set + of registers. The "ethernet-block" level describes the + shared register set, and the "ethernet" nodes describe ethernet + port-specific properties. + + Ethernet block node + + Required properties: + - #address-cells : <1> + - #size-cells : <0> + - compatible : "marvell,mv64360-eth-block" + - reg : Offset and length of the register set for this block + + Example Discovery Ethernet block node: + ethernet-block@2000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,mv64360-eth-block"; + reg = <0x2000 0x2000>; + ethernet@0 { + ....... + }; + }; + + Ethernet port node + + Required properties: + - device_type : Should be "network". + - compatible : Should be "marvell,mv64360-eth". + - reg : Should be <0>, <1>, or <2>, according to which registers + within the silicon block the device uses. + - interrupts : <a> where a is the interrupt number for the port. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + - phy : the phandle for the PHY connected to this ethernet + controller. + - local-mac-address : 6 bytes, MAC address + + Example Discovery Ethernet port node: + ethernet@0 { + device_type = "network"; + compatible = "marvell,mv64360-eth"; + reg = <0>; + interrupts = <32>; + interrupt-parent = <&PIC>; + phy = <&PHY0>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + + + + c) Marvell Discovery PHY nodes + + Required properties: + - device_type : Should be "ethernet-phy" + - interrupts : <a> where a is the interrupt number for this phy. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - reg : The ID number for the phy, usually a small integer + + Example Discovery PHY node: + ethernet-phy@1 { + device_type = "ethernet-phy"; + compatible = "broadcom,bcm5421"; + interrupts = <76>; /* GPP 12 */ + interrupt-parent = <&PIC>; + reg = <1>; + }; + + + d) Marvell Discovery SDMA nodes + + Represent DMA hardware associated with the MPSC (multiprotocol + serial controllers). + + Required properties: + - compatible : "marvell,mv64360-sdma" + - reg : Offset and length of the register set for this device + - interrupts : <a> where a is the interrupt number for the DMA + device. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery SDMA node: + sdma@4000 { + compatible = "marvell,mv64360-sdma"; + reg = <0x4000 0xc18>; + virtual-reg = <0xf1004000>; + interrupts = <36>; + interrupt-parent = <&PIC>; + }; + + + e) Marvell Discovery BRG nodes + + Represent baud rate generator hardware associated with the MPSC + (multiprotocol serial controllers). + + Required properties: + - compatible : "marvell,mv64360-brg" + - reg : Offset and length of the register set for this device + - clock-src : A value from 0 to 15 which selects the clock + source for the baud rate generator. This value corresponds + to the CLKS value in the BRGx configuration register. See + the mv64x60 User's Manual. + - clock-frequence : The frequency (in Hz) of the baud rate + generator's input clock. + - current-speed : The current speed setting (presumably by + firmware) of the baud rate generator. + + Example Discovery BRG node: + brg@b200 { + compatible = "marvell,mv64360-brg"; + reg = <0xb200 0x8>; + clock-src = <8>; + clock-frequency = <133333333>; + current-speed = <9600>; + }; + + + f) Marvell Discovery CUNIT nodes + + Represent the Serial Communications Unit device hardware. + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery CUNIT node: + cunit@f200 { + reg = <0xf200 0x200>; + }; + + + g) Marvell Discovery MPSCROUTING nodes + + Represent the Discovery's MPSC routing hardware + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery CUNIT node: + mpscrouting@b500 { + reg = <0xb400 0xc>; + }; + + + h) Marvell Discovery MPSCINTR nodes + + Represent the Discovery's MPSC DMA interrupt hardware registers + (SDMA cause and mask registers). + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery MPSCINTR node: + mpsintr@b800 { + reg = <0xb800 0x100>; + }; + + + i) Marvell Discovery MPSC nodes + + Represent the Discovery's MPSC (Multiprotocol Serial Controller) + serial port. + + Required properties: + - device_type : "serial" + - compatible : "marvell,mv64360-mpsc" + - reg : Offset and length of the register set for this device + - sdma : the phandle for the SDMA node used by this port + - brg : the phandle for the BRG node used by this port + - cunit : the phandle for the CUNIT node used by this port + - mpscrouting : the phandle for the MPSCROUTING node used by this port + - mpscintr : the phandle for the MPSCINTR node used by this port + - cell-index : the hardware index of this cell in the MPSC core + - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) + register + - interrupts : <a> where a is the interrupt number for the MPSC. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery MPSCINTR node: + mpsc@8000 { + device_type = "serial"; + compatible = "marvell,mv64360-mpsc"; + reg = <0x8000 0x38>; + virtual-reg = <0xf1008000>; + sdma = <&SDMA0>; + brg = <&BRG0>; + cunit = <&CUNIT>; + mpscrouting = <&MPSCROUTING>; + mpscintr = <&MPSCINTR>; + cell-index = <0>; + max_idle = <40>; + interrupts = <40>; + interrupt-parent = <&PIC>; + }; + + + j) Marvell Discovery Watch Dog Timer nodes + + Represent the Discovery's watchdog timer hardware + + Required properties: + - compatible : "marvell,mv64360-wdt" + - reg : Offset and length of the register set for this device + + Example Discovery Watch Dog Timer node: + wdt@b410 { + compatible = "marvell,mv64360-wdt"; + reg = <0xb410 0x8>; + }; + + + k) Marvell Discovery I2C nodes + + Represent the Discovery's I2C hardware + + Required properties: + - device_type : "i2c" + - compatible : "marvell,mv64360-i2c" + - reg : Offset and length of the register set for this device + - interrupts : <a> where a is the interrupt number for the I2C. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery I2C node: + compatible = "marvell,mv64360-i2c"; + reg = <0xc000 0x20>; + virtual-reg = <0xf100c000>; + interrupts = <37>; + interrupt-parent = <&PIC>; + }; + + + l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes + + Represent the Discovery's PIC hardware + + Required properties: + - #interrupt-cells : <1> + - #address-cells : <0> + - compatible : "marvell,mv64360-pic" + - reg : Offset and length of the register set for this device + - interrupt-controller + + Example Discovery PIC node: + pic { + #interrupt-cells = <1>; + #address-cells = <0>; + compatible = "marvell,mv64360-pic"; + reg = <0x0 0x88>; + interrupt-controller; + }; + + + m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes + + Represent the Discovery's MPP hardware + + Required properties: + - compatible : "marvell,mv64360-mpp" + - reg : Offset and length of the register set for this device + + Example Discovery MPP node: + mpp@f000 { + compatible = "marvell,mv64360-mpp"; + reg = <0xf000 0x10>; + }; + + + n) Marvell Discovery GPP (General Purpose Pins) nodes + + Represent the Discovery's GPP hardware + + Required properties: + - compatible : "marvell,mv64360-gpp" + - reg : Offset and length of the register set for this device + + Example Discovery GPP node: + gpp@f000 { + compatible = "marvell,mv64360-gpp"; + reg = <0xf100 0x20>; + }; + + + o) Marvell Discovery PCI host bridge node + + Represents the Discovery's PCI host bridge device. The properties + for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE + 1275-1994. A typical value for the compatible property is + "marvell,mv64360-pci". + + Example Discovery PCI host bridge node + pci@80000000 { + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + compatible = "marvell,mv64360-pci"; + reg = <0xcf8 0x8>; + ranges = <0x01000000 0x0 0x0 + 0x88000000 0x0 0x01000000 + 0x02000000 0x0 0x80000000 + 0x80000000 0x0 0x08000000>; + bus-range = <0 255>; + clock-frequency = <66000000>; + interrupt-parent = <&PIC>; + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; + interrupt-map = < + /* IDSEL 0x0a */ + 0x5000 0 0 1 &PIC 80 + 0x5000 0 0 2 &PIC 81 + 0x5000 0 0 3 &PIC 91 + 0x5000 0 0 4 &PIC 93 + + /* IDSEL 0x0b */ + 0x5800 0 0 1 &PIC 91 + 0x5800 0 0 2 &PIC 93 + 0x5800 0 0 3 &PIC 80 + 0x5800 0 0 4 &PIC 81 + + /* IDSEL 0x0c */ + 0x6000 0 0 1 &PIC 91 + 0x6000 0 0 2 &PIC 93 + 0x6000 0 0 3 &PIC 80 + 0x6000 0 0 4 &PIC 81 + + /* IDSEL 0x0d */ + 0x6800 0 0 1 &PIC 93 + 0x6800 0 0 2 &PIC 80 + 0x6800 0 0 3 &PIC 81 + 0x6800 0 0 4 &PIC 91 + >; + }; + + + p) Marvell Discovery CPU Error nodes + + Represent the Discovery's CPU error handler device. + + Required properties: + - compatible : "marvell,mv64360-cpu-error" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery CPU Error node: + cpu-error@0070 { + compatible = "marvell,mv64360-cpu-error"; + reg = <0x70 0x10 0x128 0x28>; + interrupts = <3>; + interrupt-parent = <&PIC>; + }; + + + q) Marvell Discovery SRAM Controller nodes + + Represent the Discovery's SRAM controller device. + + Required properties: + - compatible : "marvell,mv64360-sram-ctrl" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery SRAM Controller node: + sram-ctrl@0380 { + compatible = "marvell,mv64360-sram-ctrl"; + reg = <0x380 0x80>; + interrupts = <13>; + interrupt-parent = <&PIC>; + }; + + + r) Marvell Discovery PCI Error Handler nodes + + Represent the Discovery's PCI error handler device. + + Required properties: + - compatible : "marvell,mv64360-pci-error" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery PCI Error Handler node: + pci-error@1d40 { + compatible = "marvell,mv64360-pci-error"; + reg = <0x1d40 0x40 0xc28 0x4>; + interrupts = <12>; + interrupt-parent = <&PIC>; + }; + + + s) Marvell Discovery Memory Controller nodes + + Represent the Discovery's memory controller device. + + Required properties: + - compatible : "marvell,mv64360-mem-ctrl" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery Memory Controller node: + mem-ctrl@1400 { + compatible = "marvell,mv64360-mem-ctrl"; + reg = <0x1400 0x60>; + interrupts = <17>; + interrupt-parent = <&PIC>; + }; + + diff --git a/Documentation/powerpc/dts-bindings/phy.txt b/Documentation/powerpc/dts-bindings/phy.txt new file mode 100644 index 0000000000000..bb8c742eb8c59 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/phy.txt @@ -0,0 +1,25 @@ +PHY nodes + +Required properties: + + - device_type : Should be "ethernet-phy" + - interrupts : <a b> where a is the interrupt number and b is a + field that represents an encoding of the sense and level + information for the interrupt. This should be encoded based on + the information in section 2) depending on the type of interrupt + controller you have. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - reg : The ID number for the phy, usually a small integer + - linux,phandle : phandle for this node; likely referenced by an + ethernet controller node. + +Example: + +ethernet-phy@0 { + linux,phandle = <2452000> + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <0>; + device_type = "ethernet-phy"; +}; diff --git a/Documentation/powerpc/dts-bindings/spi-bus.txt b/Documentation/powerpc/dts-bindings/spi-bus.txt new file mode 100644 index 0000000000000..e782add2e457d --- /dev/null +++ b/Documentation/powerpc/dts-bindings/spi-bus.txt @@ -0,0 +1,57 @@ +SPI (Serial Peripheral Interface) busses + +SPI busses can be described with a node for the SPI master device +and a set of child nodes for each SPI slave on the bus. For this +discussion, it is assumed that the system's SPI controller is in +SPI master mode. This binding does not describe SPI controllers +in slave mode. + +The SPI master node requires the following properties: +- #address-cells - number of cells required to define a chip select + address on the SPI bus. +- #size-cells - should be zero. +- compatible - name of SPI bus controller following generic names + recommended practice. +No other properties are required in the SPI bus node. It is assumed +that a driver for an SPI bus device will understand that it is an SPI bus. +However, the binding does not attempt to define the specific method for +assigning chip select numbers. Since SPI chip select configuration is +flexible and non-standardized, it is left out of this binding with the +assumption that board specific platform code will be used to manage +chip selects. Individual drivers can define additional properties to +support describing the chip select layout. + +SPI slave nodes must be children of the SPI master node and can +contain the following properties. +- reg - (required) chip select address of device. +- compatible - (required) name of SPI device following generic names + recommended practice +- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz +- spi-cpol - (optional) Empty property indicating device requires + inverse clock polarity (CPOL) mode +- spi-cpha - (optional) Empty property indicating device requires + shifted clock phase (CPHA) mode +- spi-cs-high - (optional) Empty property indicating device requires + chip select active high + +SPI example for an MPC5200 SPI bus: + spi@f00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi"; + reg = <0xf00 0x20>; + interrupts = <2 13 0 2 14 0>; + interrupt-parent = <&mpc5200_pic>; + + ethernet-switch@0 { + compatible = "micrel,ks8995m"; + spi-max-frequency = <1000000>; + reg = <0>; + }; + + codec@1 { + compatible = "ti,tlv320aic26"; + spi-max-frequency = <100000>; + reg = <1>; + }; + }; diff --git a/Documentation/powerpc/dts-bindings/usb-ehci.txt b/Documentation/powerpc/dts-bindings/usb-ehci.txt new file mode 100644 index 0000000000000..fa18612f757b8 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/usb-ehci.txt @@ -0,0 +1,25 @@ +USB EHCI controllers + +Required properties: + - compatible : should be "usb-ehci". + - reg : should contain at least address and length of the standard EHCI + register set for the device. Optional platform-dependent registers + (debug-port or other) can be also specified here, but only after + definition of standard EHCI registers. + - interrupts : one EHCI interrupt should be described here. +If device registers are implemented in big endian mode, the device +node should have "big-endian-regs" property. +If controller implementation operates with big endian descriptors, +"big-endian-desc" property should be specified. +If both big endian registers and descriptors are used by the controller +implementation, "big-endian" property can be specified instead of having +both "big-endian-regs" and "big-endian-desc". + +Example (Sequoia 440EPx): + ehci@e0000300 { + compatible = "ibm,usb-ehci-440epx", "usb-ehci"; + interrupt-parent = <&UIC0>; + interrupts = <1a 4>; + reg = <0 e0000300 90 0 e0000390 70>; + big-endian; + }; diff --git a/Documentation/powerpc/dts-bindings/xilinx.txt b/Documentation/powerpc/dts-bindings/xilinx.txt new file mode 100644 index 0000000000000..80339fe4300b7 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/xilinx.txt @@ -0,0 +1,295 @@ + d) Xilinx IP cores + + The Xilinx EDK toolchain ships with a set of IP cores (devices) for use + in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range + of standard device types (network, serial, etc.) and miscellaneous + devices (gpio, LCD, spi, etc). Also, since these devices are + implemented within the fpga fabric every instance of the device can be + synthesised with different options that change the behaviour. + + Each IP-core has a set of parameters which the FPGA designer can use to + control how the core is synthesized. Historically, the EDK tool would + extract the device parameters relevant to device drivers and copy them + into an 'xparameters.h' in the form of #define symbols. This tells the + device drivers how the IP cores are configured, but it requres the kernel + to be recompiled every time the FPGA bitstream is resynthesized. + + The new approach is to export the parameters into the device tree and + generate a new device tree each time the FPGA bitstream changes. The + parameters which used to be exported as #defines will now become + properties of the device node. In general, device nodes for IP-cores + will take the following form: + + (name): (generic-name)@(base-address) { + compatible = "xlnx,(ip-core-name)-(HW_VER)" + [, (list of compatible devices), ...]; + reg = <(baseaddr) (size)>; + interrupt-parent = <&interrupt-controller-phandle>; + interrupts = < ... >; + xlnx,(parameter1) = "(string-value)"; + xlnx,(parameter2) = <(int-value)>; + }; + + (generic-name): an open firmware-style name that describes the + generic class of device. Preferably, this is one word, such + as 'serial' or 'ethernet'. + (ip-core-name): the name of the ip block (given after the BEGIN + directive in system.mhs). Should be in lowercase + and all underscores '_' converted to dashes '-'. + (name): is derived from the "PARAMETER INSTANCE" value. + (parameter#): C_* parameters from system.mhs. The C_ prefix is + dropped from the parameter name, the name is converted + to lowercase and all underscore '_' characters are + converted to dashes '-'. + (baseaddr): the baseaddr parameter value (often named C_BASEADDR). + (HW_VER): from the HW_VER parameter. + (size): the address range size (often C_HIGHADDR - C_BASEADDR + 1). + + Typically, the compatible list will include the exact IP core version + followed by an older IP core version which implements the same + interface or any other device with the same interface. + + 'reg', 'interrupt-parent' and 'interrupts' are all optional properties. + + For example, the following block from system.mhs: + + BEGIN opb_uartlite + PARAMETER INSTANCE = opb_uartlite_0 + PARAMETER HW_VER = 1.00.b + PARAMETER C_BAUDRATE = 115200 + PARAMETER C_DATA_BITS = 8 + PARAMETER C_ODD_PARITY = 0 + PARAMETER C_USE_PARITY = 0 + PARAMETER C_CLK_FREQ = 50000000 + PARAMETER C_BASEADDR = 0xEC100000 + PARAMETER C_HIGHADDR = 0xEC10FFFF + BUS_INTERFACE SOPB = opb_7 + PORT OPB_Clk = CLK_50MHz + PORT Interrupt = opb_uartlite_0_Interrupt + PORT RX = opb_uartlite_0_RX + PORT TX = opb_uartlite_0_TX + PORT OPB_Rst = sys_bus_reset_0 + END + + becomes the following device tree node: + + opb_uartlite_0: serial@ec100000 { + device_type = "serial"; + compatible = "xlnx,opb-uartlite-1.00.b"; + reg = <ec100000 10000>; + interrupt-parent = <&opb_intc_0>; + interrupts = <1 0>; // got this from the opb_intc parameters + current-speed = <d#115200>; // standard serial device prop + clock-frequency = <d#50000000>; // standard serial device prop + xlnx,data-bits = <8>; + xlnx,odd-parity = <0>; + xlnx,use-parity = <0>; + }; + + Some IP cores actually implement 2 or more logical devices. In + this case, the device should still describe the whole IP core with + a single node and add a child node for each logical device. The + ranges property can be used to translate from parent IP-core to the + registers of each device. In addition, the parent node should be + compatible with the bus type 'xlnx,compound', and should contain + #address-cells and #size-cells, as with any other bus. (Note: this + makes the assumption that both logical devices have the same bus + binding. If this is not true, then separate nodes should be used + for each logical device). The 'cell-index' property can be used to + enumerate logical devices within an IP core. For example, the + following is the system.mhs entry for the dual ps2 controller found + on the ml403 reference design. + + BEGIN opb_ps2_dual_ref + PARAMETER INSTANCE = opb_ps2_dual_ref_0 + PARAMETER HW_VER = 1.00.a + PARAMETER C_BASEADDR = 0xA9000000 + PARAMETER C_HIGHADDR = 0xA9001FFF + BUS_INTERFACE SOPB = opb_v20_0 + PORT Sys_Intr1 = ps2_1_intr + PORT Sys_Intr2 = ps2_2_intr + PORT Clkin1 = ps2_clk_rx_1 + PORT Clkin2 = ps2_clk_rx_2 + PORT Clkpd1 = ps2_clk_tx_1 + PORT Clkpd2 = ps2_clk_tx_2 + PORT Rx1 = ps2_d_rx_1 + PORT Rx2 = ps2_d_rx_2 + PORT Txpd1 = ps2_d_tx_1 + PORT Txpd2 = ps2_d_tx_2 + END + + It would result in the following device tree nodes: + + opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,compound"; + ranges = <0 a9000000 2000>; + // If this device had extra parameters, then they would + // go here. + ps2@0 { + compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; + reg = <0 40>; + interrupt-parent = <&opb_intc_0>; + interrupts = <3 0>; + cell-index = <0>; + }; + ps2@1000 { + compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; + reg = <1000 40>; + interrupt-parent = <&opb_intc_0>; + interrupts = <3 0>; + cell-index = <0>; + }; + }; + + Also, the system.mhs file defines bus attachments from the processor + to the devices. The device tree structure should reflect the bus + attachments. Again an example; this system.mhs fragment: + + BEGIN ppc405_virtex4 + PARAMETER INSTANCE = ppc405_0 + PARAMETER HW_VER = 1.01.a + BUS_INTERFACE DPLB = plb_v34_0 + BUS_INTERFACE IPLB = plb_v34_0 + END + + BEGIN opb_intc + PARAMETER INSTANCE = opb_intc_0 + PARAMETER HW_VER = 1.00.c + PARAMETER C_BASEADDR = 0xD1000FC0 + PARAMETER C_HIGHADDR = 0xD1000FDF + BUS_INTERFACE SOPB = opb_v20_0 + END + + BEGIN opb_uart16550 + PARAMETER INSTANCE = opb_uart16550_0 + PARAMETER HW_VER = 1.00.d + PARAMETER C_BASEADDR = 0xa0000000 + PARAMETER C_HIGHADDR = 0xa0001FFF + BUS_INTERFACE SOPB = opb_v20_0 + END + + BEGIN plb_v34 + PARAMETER INSTANCE = plb_v34_0 + PARAMETER HW_VER = 1.02.a + END + + BEGIN plb_bram_if_cntlr + PARAMETER INSTANCE = plb_bram_if_cntlr_0 + PARAMETER HW_VER = 1.00.b + PARAMETER C_BASEADDR = 0xFFFF0000 + PARAMETER C_HIGHADDR = 0xFFFFFFFF + BUS_INTERFACE SPLB = plb_v34_0 + END + + BEGIN plb2opb_bridge + PARAMETER INSTANCE = plb2opb_bridge_0 + PARAMETER HW_VER = 1.01.a + PARAMETER C_RNG0_BASEADDR = 0x20000000 + PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF + PARAMETER C_RNG1_BASEADDR = 0x60000000 + PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF + PARAMETER C_RNG2_BASEADDR = 0x80000000 + PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF + PARAMETER C_RNG3_BASEADDR = 0xC0000000 + PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF + BUS_INTERFACE SPLB = plb_v34_0 + BUS_INTERFACE MOPB = opb_v20_0 + END + + Gives this device tree (some properties removed for clarity): + + plb@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,plb-v34-1.02.a"; + device_type = "ibm,plb"; + ranges; // 1:1 translation + + plb_bram_if_cntrl_0: bram@ffff0000 { + reg = <ffff0000 10000>; + } + + opb@20000000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <20000000 20000000 20000000 + 60000000 60000000 20000000 + 80000000 80000000 40000000 + c0000000 c0000000 20000000>; + + opb_uart16550_0: serial@a0000000 { + reg = <a00000000 2000>; + }; + + opb_intc_0: interrupt-controller@d1000fc0 { + reg = <d1000fc0 20>; + }; + }; + }; + + That covers the general approach to binding xilinx IP cores into the + device tree. The following are bindings for specific devices: + + i) Xilinx ML300 Framebuffer + + Simple framebuffer device from the ML300 reference design (also on the + ML403 reference design as well as others). + + Optional properties: + - resolution = <xres yres> : pixel resolution of framebuffer. Some + implementations use a different resolution. + Default is <d#640 d#480> + - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory. + Default is <d#1024 d#480>. + - rotate-display (empty) : rotate display 180 degrees. + + ii) Xilinx SystemACE + + The Xilinx SystemACE device is used to program FPGAs from an FPGA + bitstream stored on a CF card. It can also be used as a generic CF + interface device. + + Optional properties: + - 8-bit (empty) : Set this property for SystemACE in 8 bit mode + + iii) Xilinx EMAC and Xilinx TEMAC + + Xilinx Ethernet devices. In addition to general xilinx properties + listed above, nodes for these devices should include a phy-handle + property, and may include other common network device properties + like local-mac-address. + + iv) Xilinx Uartlite + + Xilinx uartlite devices are simple fixed speed serial ports. + + Required properties: + - current-speed : Baud rate of uartlite + + v) Xilinx hwicap + + Xilinx hwicap devices provide access to the configuration logic + of the FPGA through the Internal Configuration Access Port + (ICAP). The ICAP enables partial reconfiguration of the FPGA, + readback of the configuration information, and some control over + 'warm boots' of the FPGA fabric. + + Required properties: + - xlnx,family : The family of the FPGA, necessary since the + capabilities of the underlying ICAP hardware + differ between different families. May be + 'virtex2p', 'virtex4', or 'virtex5'. + + vi) Xilinx Uart 16550 + + Xilinx UART 16550 devices are very similar to the NS16550 but with + different register spacing and an offset from the base address. + + Required properties: + - clock-frequency : Frequency of the clock input + - reg-offset : A value of 3 is required + - reg-shift : A value of 2 is required + + -- GitLab From 6cc7959f385abc77abdeda5462f96407a556265a Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Sat, 20 Jun 2009 19:16:59 +0800 Subject: [PATCH 0078/1002] powerpc/85xx: remove duplicated #include Remove duplicated #include in arch/powerpc/platforms/85xx/xes_mpc85xx.c. Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/platforms/85xx/xes_mpc85xx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c index ee01532786e4e..1b426050a2f91 100644 --- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c +++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c @@ -32,7 +32,6 @@ #include <sysdev/fsl_soc.h> #include <sysdev/fsl_pci.h> -#include <linux/of_platform.h> /* A few bit definitions needed for fixups on some boards */ #define MPC85xx_L2CTL_L2E 0x80000000 /* L2 enable */ -- GitLab From 66c6b856d8738278a4a6e558d25c90e9950aa112 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov <avorontsov@ru.mvista.com> Date: Fri, 19 Jun 2009 03:37:52 +0400 Subject: [PATCH 0079/1002] powerpc/85xx: Make eSDHC 1-bit only transfer mode default for MPC8569E-MDS For yet unknown reason 4-bit mode doesn't work on MPC8569E-MDS boards, so make 1-bit mode default. When we resolve the issue, u-boot will remove sdhci,1-bit-only property from the device tree, while SDHCI will still work with older u-boots. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/boot/dts/mpc8569mds.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index a8dcb018c4a59..a680165292f24 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts @@ -253,6 +253,7 @@ sdhci@2e000 { /* Filled in by U-Boot */ clock-frequency = <0>; status = "disabled"; + sdhci,1-bit-only; }; crypto@30000 { -- GitLab From 503dcbeba50fd3545283594bc391b4a400fa6c48 Mon Sep 17 00:00:00 2001 From: Tony Lindgren <tony@atomide.com> Date: Tue, 23 Jun 2009 16:55:30 +0300 Subject: [PATCH 0080/1002] OMAP: Fix IOMEM macro for assembly Otherwise IOMEM calculations can fail. Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/plat-omap/include/mach/io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h index 3b28147205691..73f483d56ca6a 100644 --- a/arch/arm/plat-omap/include/mach/io.h +++ b/arch/arm/plat-omap/include/mach/io.h @@ -201,7 +201,7 @@ #define OMAP2_IO_ADDRESS(pa) IOMEM(__OMAP2_IO_ADDRESS(pa)) #ifdef __ASSEMBLER__ -#define IOMEM(x) x +#define IOMEM(x) (x) #else #define IOMEM(x) ((void __force __iomem *)(x)) -- GitLab From b0a28589b2fc9bee8ed83dee006a497d1ce93841 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Tue, 23 Jun 2009 16:39:53 +0200 Subject: [PATCH 0081/1002] perf report: Fix help text typo Reported-by: Brice Goglin <Brice.Goglin@inria.fr> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Documentation/perf-report.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 52d3fc6846a97..40c1db83a16da 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -13,7 +13,7 @@ SYNOPSIS DESCRIPTION ----------- This command displays the performance counter profile information recorded -via perf report. +via perf record. OPTIONS ------- -- GitLab From 927dbcd668ede8d2210cc59bea548ca9ff45b240 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben@simtec.co.uk> Date: Tue, 23 Jun 2009 16:15:38 +0100 Subject: [PATCH 0082/1002] [ARM] S3C24XX: Fix spi-bus configuration build errors The commit ec976d6eb021dc8f2994248c310a41540f4756bd removed a number of gpio definitions from <mach/hardware.h> but misssed updating these two files: Fix the following build errors by including <linux/gpio.h>: arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c: In function 's3c24xx_spi_gpiocfg_bus1_gpg5_6_7': arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c:25: error: implicit declaration of function 's3c2410_gpio_cfgpin' arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c:28: error: implicit declaration of function 's3c2410_gpio_pullup' arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c: In function 's3c24xx_spi_gpiocfg_bus0_gpe11_12_13': arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c:25: error: implicit declaration of function 's3c2410_gpio_cfgpin' arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c:28: error: implicit declaration of function 's3c2410_gpio_pullup' Signed-off-by: Ben Dooks <ben@simtec.co.uk> Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c | 3 +-- arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c index 9edf7894eedd6..da7a61728c18e 100644 --- a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c +++ b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c @@ -12,8 +12,7 @@ */ #include <linux/kernel.h> - -#include <mach/hardware.h> +#include <linux/gpio.h> #include <mach/spi.h> #include <mach/regs-gpio.h> diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c index f34d0fc69ad81..86b9edc674133 100644 --- a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c @@ -12,8 +12,7 @@ */ #include <linux/kernel.h> - -#include <mach/hardware.h> +#include <linux/gpio.h> #include <mach/spi.h> #include <mach/regs-gpio.h> -- GitLab From ffd14417bdf2a1650bcb16d37c7e658535d1681a Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Tue, 23 Jun 2009 20:58:57 +0800 Subject: [PATCH 0083/1002] [ARM] MINI2440: remove duplicated #include Remove duplicated #include('s) in arch/arm/mach-s3c2440/mach-mini2440.c Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/mach-s3c2440/mach-mini2440.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index 6a5bc3021bdb6..e714bfabbc09e 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -48,8 +48,6 @@ #include <plat/mci.h> #include <plat/udc.h> -#include <plat/regs-serial.h> - #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> -- GitLab From a3c79901170aba0d3717c2602326bab639eb1344 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Tue, 23 Jun 2009 16:30:02 +0100 Subject: [PATCH 0084/1002] [ARM] S3C24XX: Fix missing s3c_iis_device. Commit 52da219e9664e537a745877b0efa7cf2b1ff2996 removed the s3c_device_iis, but didn't replace it with anything so a number of s3c24xx machines are currently failing to build. As a temporary fix, re-instate s3c_device_iis until a proper replacement can be done for it. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/plat-s3c/include/plat/devs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index b5b9c4d46e9a3..2e170827e0b07 100644 --- a/arch/arm/plat-s3c/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -37,6 +37,7 @@ extern struct platform_device s3c_device_i2c1; extern struct platform_device s3c_device_rtc; extern struct platform_device s3c_device_adc; extern struct platform_device s3c_device_sdi; +extern struct platform_device s3c_device_iis; extern struct platform_device s3c_device_hwmon; extern struct platform_device s3c_device_hsmmc0; extern struct platform_device s3c_device_hsmmc1; -- GitLab From b647712f669f4fadf428a14ab45ab4c03558cdf5 Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Tue, 23 Jun 2009 16:34:35 +0100 Subject: [PATCH 0085/1002] [ARM] S3C: Fix S3C24XX build to not include s3c64xx IIS devices Commit 52da219e9664e537a745877b0efa7cf2b1ff2996 added IIS platform devices, but these do not build on s3c24xx systems and the file depends on SND_S3C24XX_SOC, which is selected for all S3C64XX/S3C24XX systems. As a quick fix, make the dev-audio.o file depends on SND_S3C64XX_SOC_I2S instead. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/plat-s3c/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile index 74bb7cb5da495..0761766b18332 100644 --- a/arch/arm/plat-s3c/Makefile +++ b/arch/arm/plat-s3c/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o -obj-$(CONFIG_SND_S3C24XX_SOC) += dev-audio.o +obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += dev-audio.o obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o -- GitLab From b5aa8a0fc132dd512c33e7c2621d075e3b77a65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Henry?= <Gregoire.Henry@pps.jussieu.fr> Date: Tue, 23 Jun 2009 15:41:02 +0200 Subject: [PATCH 0086/1002] drm/i915: initialize fence registers to zero when loading GEM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unitialized fence register could leads to corrupted display. Problem encountered on MacBooks (revision 1 and 2), directly booting from EFI or through BIOS emulation. (bug #21710 at freedestop.org) Signed-off-by: Grégoire Henry <henry@pps.jussieu.fr> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8660b2144b27a..876b65cb7629f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4227,6 +4227,7 @@ i915_gem_lastclose(struct drm_device *dev) void i915_gem_load(struct drm_device *dev) { + int i; drm_i915_private_t *dev_priv = dev->dev_private; spin_lock_init(&dev_priv->mm.active_list_lock); @@ -4246,6 +4247,18 @@ i915_gem_load(struct drm_device *dev) else dev_priv->num_fence_regs = 8; + /* Initialize fence registers to zero */ + if (IS_I965G(dev)) { + for (i = 0; i < 16; i++) + I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); + } else { + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); + } + i915_gem_detect_bit_6_swizzle(dev); } -- GitLab From 622a8f5f7bf160507861cf05309020049f42976d Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Tue, 23 Jun 2009 18:20:10 +0100 Subject: [PATCH 0087/1002] [ARM] s3c2410_defconfig: add MINI2440 machine to build Add the MINI2440 to the list of machines built by the central defconfig. Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/configs/s3c2410_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index f4f1899f3c885..b49810461e41f 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -260,6 +260,7 @@ CONFIG_MACH_NEXCODER_2440=y CONFIG_SMDK2440_CPU2440=y CONFIG_MACH_AT2440EVB=y CONFIG_CPU_S3C2442=y +CONFIG_MACH_MINI2440=y # # S3C2442 Machines -- GitLab From 51af243c631d9d03376d1454a24cf0a96e6f17cb Mon Sep 17 00:00:00 2001 From: Ben Dooks <ben-linux@fluff.org> Date: Tue, 23 Jun 2009 18:23:27 +0100 Subject: [PATCH 0088/1002] [ARM] MINI2440: Add missing flash_bbt flat to NAND The commit 9db41f9edcb87ae050fcb171c44be7f212728d54 added the .flash_bbt flag to the nand set, so add this back into the mach-mini2440.c file (taken out on initial commit to allow build). Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/mach-s3c2440/mach-mini2440.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index e714bfabbc09e..ec71a69657867 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -273,6 +273,7 @@ static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = { .nr_chips = 1, .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part), .partitions = mini2440_default_nand_part, + .flash_bbt = 1, /* we use u-boot to create a BBT */ }, }; -- GitLab From b8389018212e8c4e03ede4df5405796100ef4390 Mon Sep 17 00:00:00 2001 From: Kim Kyuwon <chammoru@gmail.com> Date: Wed, 10 Jun 2009 12:48:48 -0700 Subject: [PATCH 0089/1002] leds: fix led-bd2802 errors while resuming LED_CORE_SUSPENDRESUME flag is not needed in the bd2802 driver, because all works for suspend/resume is done in bd2802_suspend and bd2802_suspend functions. And this patch allows bd2802 to be configured again when it resumes from suspend. Signed-off-by: Kim Kyuwon <q1.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/leds-bd2802.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 4149ecb3a9b2f..6832b9fd04227 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -538,7 +538,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) led->cdev_led1r.brightness = LED_OFF; led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; led->cdev_led1r.blink_set = bd2802_set_led1r_blink; - led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME; ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); if (ret < 0) { @@ -551,7 +550,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) led->cdev_led1g.brightness = LED_OFF; led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; led->cdev_led1g.blink_set = bd2802_set_led1g_blink; - led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME; ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); if (ret < 0) { @@ -564,7 +562,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) led->cdev_led1b.brightness = LED_OFF; led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; led->cdev_led1b.blink_set = bd2802_set_led1b_blink; - led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME; ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); if (ret < 0) { @@ -577,7 +574,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) led->cdev_led2r.brightness = LED_OFF; led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; led->cdev_led2r.blink_set = bd2802_set_led2r_blink; - led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME; ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); if (ret < 0) { @@ -590,7 +586,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) led->cdev_led2g.brightness = LED_OFF; led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; led->cdev_led2g.blink_set = bd2802_set_led2g_blink; - led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME; ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); if (ret < 0) { @@ -723,8 +718,7 @@ static int bd2802_resume(struct i2c_client *client) struct bd2802_led *led = i2c_get_clientdata(client); if (!bd2802_is_all_off(led) || led->adf_on) { - gpio_set_value(led->pdata->reset_gpio, 1); - udelay(100); + bd2802_reset_cancel(led); bd2802_restore_state(led); } -- GitLab From 1b18cf413f63ff6de5ba3e5028e869c21322a4df Mon Sep 17 00:00:00 2001 From: Kim Kyuwon <chammoru@gmail.com> Date: Wed, 10 Jun 2009 12:48:50 -0700 Subject: [PATCH 0090/1002] leds: change the license information Change the license to 'GPL v2' Signed-off-by: Kim Kyuwon <q1.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/leds-bd2802.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 6832b9fd04227..7a03efd54f69d 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -756,4 +756,4 @@ module_exit(bd2802_exit); MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); MODULE_DESCRIPTION("BD2802 LED driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- GitLab From 8792f7cf4368f9bc337eee65851d8e7abbbf946c Mon Sep 17 00:00:00 2001 From: Kim Kyuwon <chammoru@gmail.com> Date: Wed, 10 Jun 2009 12:48:50 -0700 Subject: [PATCH 0091/1002] leds: add the sysfs interface into the leds-bd2802 driver for changing wave pattern and led current. Allow the user application to change the wave pattern and led current by 'wave_pattern' and 'rgb_current' sysfs files. Signed-off-by: Kim Kyuwon <q1.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/leds-bd2802.c | 86 ++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 7a03efd54f69d..779d7f262c04c 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -97,6 +97,10 @@ struct bd2802_led { enum led_ids led_id; enum led_colors color; enum led_bits state; + + /* General attributes of RGB LEDs */ + int wave_pattern; + int rgb_current; }; @@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id, bd2802_reset_cancel(led); reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); - bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); + bd2802_write_byte(led->client, reg, led->rgb_current); reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); @@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id, reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); - bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); + bd2802_write_byte(led->client, reg, led->rgb_current); reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); - bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF); + bd2802_write_byte(led->client, reg, led->wave_pattern); bd2802_enable(led, id); bd2802_update_state(led, id, color, BD2802_BLINK); @@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led) ret = device_create_file(&led->client->dev, bd2802_addr_attributes[i]); if (ret) { - dev_err(&led->client->dev, "failed to sysfs file %s\n", + dev_err(&led->client->dev, "failed: sysfs file %s\n", bd2802_addr_attributes[i]->attr.name); goto failed_remove_files; } @@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = { .store = bd2802_store_adv_conf, }; +#define BD2802_CONTROL_ATTR(attr_name, name_str) \ +static ssize_t bd2802_show_##attr_name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ + ssize_t ret; \ + down_read(&led->rwsem); \ + ret = sprintf(buf, "0x%02x\n", led->attr_name); \ + up_read(&led->rwsem); \ + return ret; \ +} \ +static ssize_t bd2802_store_##attr_name(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ + unsigned long val; \ + int ret; \ + if (!count) \ + return -EINVAL; \ + ret = strict_strtoul(buf, 16, &val); \ + if (ret) \ + return ret; \ + down_write(&led->rwsem); \ + led->attr_name = val; \ + up_write(&led->rwsem); \ + return count; \ +} \ +static struct device_attribute bd2802_##attr_name##_attr = { \ + .attr = { \ + .name = name_str, \ + .mode = 0644, \ + .owner = THIS_MODULE \ + }, \ + .show = bd2802_show_##attr_name, \ + .store = bd2802_store_##attr_name, \ +}; + +BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern"); +BD2802_CONTROL_ATTR(rgb_current, "rgb_current"); + +static struct device_attribute *bd2802_attributes[] = { + &bd2802_adv_conf_attr, + &bd2802_wave_pattern_attr, + &bd2802_rgb_current_attr, +}; + static void bd2802_led_work(struct work_struct *work) { struct bd2802_led *led = container_of(work, struct bd2802_led, work); @@ -635,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, { struct bd2802_led *led; struct bd2802_led_platform_data *pdata; - int ret; + int ret, i; led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); if (!led) { @@ -665,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client, /* To save the power, reset BD2802 after detecting */ gpio_set_value(led->pdata->reset_gpio, 0); + /* Default attributes */ + led->wave_pattern = BD2802_PATTERN_HALF; + led->rgb_current = BD2802_CURRENT_032; + init_rwsem(&led->rwsem); - ret = device_create_file(&client->dev, &bd2802_adv_conf_attr); - if (ret) { - dev_err(&client->dev, "failed to create sysfs file %s\n", - bd2802_adv_conf_attr.attr.name); - goto failed_free; + for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) { + ret = device_create_file(&led->client->dev, + bd2802_attributes[i]); + if (ret) { + dev_err(&led->client->dev, "failed: sysfs file %s\n", + bd2802_attributes[i]->attr.name); + goto failed_unregister_dev_file; + } } ret = bd2802_register_led_classdev(led); @@ -681,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client, return 0; failed_unregister_dev_file: - device_remove_file(&client->dev, &bd2802_adv_conf_attr); + for (i--; i >= 0; i--) + device_remove_file(&led->client->dev, bd2802_attributes[i]); failed_free: i2c_set_clientdata(client, NULL); kfree(led); @@ -692,12 +750,14 @@ static int __devinit bd2802_probe(struct i2c_client *client, static int __exit bd2802_remove(struct i2c_client *client) { struct bd2802_led *led = i2c_get_clientdata(client); + int i; - bd2802_unregister_led_classdev(led); gpio_set_value(led->pdata->reset_gpio, 0); + bd2802_unregister_led_classdev(led); if (led->adf_on) bd2802_disable_adv_conf(led); - device_remove_file(&client->dev, &bd2802_adv_conf_attr); + for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) + device_remove_file(&led->client->dev, bd2802_attributes[i]); i2c_set_clientdata(client, NULL); kfree(led); -- GitLab From 7fd02170e25b3b60fc21cd7b64bf1ed42e6a7cbe Mon Sep 17 00:00:00 2001 From: Zhenwen Xu <helight.xu@gmail.com> Date: Wed, 10 Jun 2009 12:48:51 -0700 Subject: [PATCH 0092/1002] leds: leds-gpio - fix a section mismatch WARNING: drivers/leds/leds-gpio.o(.text+0x153): Section mismatch in reference from the function gpio_led_probe() to the function .devinit.text:create_gpio_led() The function gpio_led_probe() references the function __devinit create_gpio_led(). This is often because gpio_led_probe lacks a __devinit annotation or the annotation of create_gpio_led is wrong. Signed-off-by: Zhenwen Xu <helight.xu@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/leds-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index d2109054de858..76895e691042d 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -129,7 +129,7 @@ static void delete_gpio_led(struct gpio_led_data *led) } #ifdef CONFIG_LEDS_GPIO_PLATFORM -static int gpio_led_probe(struct platform_device *pdev) +static int __devinit gpio_led_probe(struct platform_device *pdev) { struct gpio_led_platform_data *pdata = pdev->dev.platform_data; struct gpio_led_data *leds_data; -- GitLab From 2216c6e83ccbc9d34f541621ff23f510cd8a256f Mon Sep 17 00:00:00 2001 From: Tobias Mueller <Tobias_Mueller@twam.info> Date: Wed, 10 Jun 2009 12:48:52 -0700 Subject: [PATCH 0093/1002] leds: alix-leds2 fixed for Award BIOS Add initialisation of GPIO ports for compatibility with boards with Award BIOS (e.g. ALIX.3D3). Signed-off-by: Tobias Mueller <Tobias_Mueller@twam.info> Reviewed-by: Constantin Baranov <const@mimas.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/Kconfig | 1 + drivers/leds/leds-alix2.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9b60b6b684d9c..37e91184756d6 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -75,6 +75,7 @@ config LEDS_ALIX2 depends on LEDS_CLASS && X86 && EXPERIMENTAL help This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. + You have to set leds-alix2.force=1 for boards with Award BIOS. config LEDS_H1940 tristate "LED Support for iPAQ H1940 device" diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c index ddbd7730dfc84..731d4eef34259 100644 --- a/drivers/leds/leds-alix2.c +++ b/drivers/leds/leds-alix2.c @@ -14,7 +14,7 @@ static int force = 0; module_param(force, bool, 0444); -MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs"); +MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs"); struct alix_led { struct led_classdev cdev; @@ -155,6 +155,11 @@ static int __init alix_led_init(void) goto out; } + /* enable output on GPIO for LED 1,2,3 */ + outl(1 << 6, 0x6104); + outl(1 << 9, 0x6184); + outl(1 << 11, 0x6184); + pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); if (!IS_ERR(pdev)) { ret = platform_driver_probe(&alix_led_driver, alix_led_probe); -- GitLab From 92722b1bb1ebcba767f9c6ee499992ee33367268 Mon Sep 17 00:00:00 2001 From: Mark Brown <broonie@opensource.wolfsonmicro.com> Date: Thu, 11 Jun 2009 14:17:48 +0100 Subject: [PATCH 0094/1002] leds: Further document parameters for blink_set() The documentation for the parameters of blink_set() was a bit hard to find so put some where I'd expected to find it. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- include/linux/leds.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/leds.h b/include/linux/leds.h index 376fe07732ea9..c7f0b148df060 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -45,7 +45,9 @@ struct led_classdev { /* Get LED brightness level */ enum led_brightness (*brightness_get)(struct led_classdev *led_cdev); - /* Activate hardware accelerated blink */ + /* Activate hardware accelerated blink, delays are in + * miliseconds and if none is provided then a sensible default + * should be chosen. */ int (*blink_set)(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off); -- GitLab From 34abdf252699ebc549fad54c1db481612f22a826 Mon Sep 17 00:00:00 2001 From: Richard Purdie <rpurdie@linux.intel.com> Date: Wed, 17 Jun 2009 13:05:27 +0100 Subject: [PATCH 0095/1002] leds: Remove an orphan Kconfig entry Remove an orphan Kconfig entry (LEDS_LP5521) Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 37e91184756d6..cfcd6bf831c9b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -146,16 +146,6 @@ config LEDS_GPIO_OF of_platform devices. For instance, LEDs which are listed in a "dts" file. -config LEDS_LP5521 - tristate "LED Support for the LP5521 LEDs" - depends on LEDS_CLASS && I2C - help - If you say 'Y' here you get support for the National Semiconductor - LP5521 LED driver used in n8x0 boards. - - This driver can be built as a module by choosing 'M'. The module - will be called leds-lp5521. - config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook" depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI -- GitLab From 07172d2bfa339d6c150d8cdd7c02128177feffbb Mon Sep 17 00:00:00 2001 From: Antonio Ospite <ospite@studenti.unina.it> Date: Fri, 19 Jun 2009 13:53:07 +0200 Subject: [PATCH 0096/1002] leds: pca9532 - Indent using tabs, not spaces. Indent using tabs, not spaces. Signed-off-by: Antonio Ospite <ospite@studenti.unina.it> Acked-by: Riku Voipio <riku.voipio@iki.fi> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/leds/leds-pca9532.c | 58 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 3937244fdcab8..dba8921240f26 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -35,7 +35,7 @@ struct pca9532_data { struct pca9532_led leds[16]; struct mutex update_lock; struct input_dev *idev; - struct work_struct work; + struct work_struct work; u8 pwm[2]; u8 psc[2]; }; @@ -87,14 +87,14 @@ static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink, if (b > 0xFF) return -EINVAL; data->pwm[pwm] = b; - data->psc[pwm] = blink; - return 0; + data->psc[pwm] = blink; + return 0; } static int pca9532_setpwm(struct i2c_client *client, int pwm) { - struct pca9532_data *data = i2c_get_clientdata(client); - mutex_lock(&data->update_lock); + struct pca9532_data *data = i2c_get_clientdata(client); + mutex_lock(&data->update_lock); i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), data->pwm[pwm]); i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), @@ -132,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev, led->state = PCA9532_ON; else { led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ - err = pca9532_calcpwm(led->client, 0, 0, value); + err = pca9532_calcpwm(led->client, 0, 0, value); if (err) return; /* XXX: led api doesn't allow error code? */ } - schedule_work(&led->work); + schedule_work(&led->work); } static int pca9532_set_blink(struct led_classdev *led_cdev, @@ -145,7 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, struct pca9532_led *led = ldev_to_led(led_cdev); struct i2c_client *client = led->client; int psc; - int err = 0; + int err = 0; if (*delay_on == 0 && *delay_off == 0) { /* led subsystem ask us for a blink rate */ @@ -157,11 +157,11 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, /* Thecus specific: only use PSC/PWM 0 */ psc = (*delay_on * 152-1)/1000; - err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); - if (err) - return err; - schedule_work(&led->work); - return 0; + err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); + if (err) + return err; + schedule_work(&led->work); + return 0; } static int pca9532_event(struct input_dev *dev, unsigned int type, @@ -178,15 +178,15 @@ static int pca9532_event(struct input_dev *dev, unsigned int type, else data->pwm[1] = 0; - schedule_work(&data->work); + schedule_work(&data->work); - return 0; + return 0; } static void pca9532_input_work(struct work_struct *work) { - struct pca9532_data *data; - data = container_of(work, struct pca9532_data, work); + struct pca9532_data *data; + data = container_of(work, struct pca9532_data, work); mutex_lock(&data->update_lock); i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), data->pwm[1]); @@ -195,11 +195,11 @@ static void pca9532_input_work(struct work_struct *work) static void pca9532_led_work(struct work_struct *work) { - struct pca9532_led *led; - led = container_of(work, struct pca9532_led, work); - if (led->state == PCA9532_PWM0) - pca9532_setpwm(led->client, 0); - pca9532_setled(led); + struct pca9532_led *led; + led = container_of(work, struct pca9532_led, work); + if (led->state == PCA9532_PWM0) + pca9532_setpwm(led->client, 0); + pca9532_setled(led); } static int pca9532_configure(struct i2c_client *client, @@ -232,7 +232,7 @@ static int pca9532_configure(struct i2c_client *client, led->ldev.brightness = LED_OFF; led->ldev.brightness_set = pca9532_set_brightness; led->ldev.blink_set = pca9532_set_blink; - INIT_WORK(&led->work, pca9532_led_work); + INIT_WORK(&led->work, pca9532_led_work); err = led_classdev_register(&client->dev, &led->ldev); if (err < 0) { dev_err(&client->dev, @@ -262,11 +262,11 @@ static int pca9532_configure(struct i2c_client *client, BIT_MASK(SND_TONE); data->idev->event = pca9532_event; input_set_drvdata(data->idev, data); - INIT_WORK(&data->work, pca9532_input_work); + INIT_WORK(&data->work, pca9532_input_work); err = input_register_device(data->idev); if (err) { input_free_device(data->idev); - cancel_work_sync(&data->work); + cancel_work_sync(&data->work); data->idev = NULL; goto exit; } @@ -283,13 +283,13 @@ static int pca9532_configure(struct i2c_client *client, break; case PCA9532_TYPE_LED: led_classdev_unregister(&data->leds[i].ldev); - cancel_work_sync(&data->leds[i].work); + cancel_work_sync(&data->leds[i].work); break; case PCA9532_TYPE_N2100_BEEP: if (data->idev != NULL) { input_unregister_device(data->idev); input_free_device(data->idev); - cancel_work_sync(&data->work); + cancel_work_sync(&data->work); data->idev = NULL; } break; @@ -340,13 +340,13 @@ static int pca9532_remove(struct i2c_client *client) break; case PCA9532_TYPE_LED: led_classdev_unregister(&data->leds[i].ldev); - cancel_work_sync(&data->leds[i].work); + cancel_work_sync(&data->leds[i].work); break; case PCA9532_TYPE_N2100_BEEP: if (data->idev != NULL) { input_unregister_device(data->idev); input_free_device(data->idev); - cancel_work_sync(&data->work); + cancel_work_sync(&data->work); data->idev = NULL; } break; -- GitLab From 5054d39e327f76df022163a2ebd02e444c5d65f9 Mon Sep 17 00:00:00 2001 From: Antonio Ospite <ospite@studenti.unina.it> Date: Fri, 19 Jun 2009 13:55:42 +0200 Subject: [PATCH 0097/1002] leds: LED driver for National Semiconductor LP3944 Funlight Chip LEDs driver for National Semiconductor LP3944 Funlight Chip http://www.national.com/pf/LP/LP3944.html This helper chip can drive up to 8 leds, with two programmable DIM modes; it could even be used as a gpio expander but this driver assumes it is used as a led controller. The DIM modes are used to set _blink_ patterns for leds, the pattern is specified supplying two parameters: - period: from 0s to 1.6s - duty cycle: percentage of the period the led is on, from 0 to 100 LP3944 can be found on Motorola A910 smartphone, where it drives the rgb leds, the camera flash light and the displays backlights. Signed-off-by: Antonio Ospite <ospite@studenti.unina.it> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- Documentation/leds-lp3944.txt | 50 ++++ drivers/leds/Kconfig | 11 + drivers/leds/Makefile | 1 + drivers/leds/leds-lp3944.c | 466 ++++++++++++++++++++++++++++++++++ include/linux/leds-lp3944.h | 53 ++++ 5 files changed, 581 insertions(+) create mode 100644 Documentation/leds-lp3944.txt create mode 100644 drivers/leds/leds-lp3944.c create mode 100644 include/linux/leds-lp3944.h diff --git a/Documentation/leds-lp3944.txt b/Documentation/leds-lp3944.txt new file mode 100644 index 0000000000000..c6eda18b15efb --- /dev/null +++ b/Documentation/leds-lp3944.txt @@ -0,0 +1,50 @@ +Kernel driver lp3944 +==================== + + * National Semiconductor LP3944 Fun-light Chip + Prefix: 'lp3944' + Addresses scanned: None (see the Notes section below) + Datasheet: Publicly available at the National Semiconductor website + http://www.national.com/pf/LP/LP3944.html + +Authors: + Antonio Ospite <ospite@studenti.unina.it> + + +Description +----------- +The LP3944 is a helper chip that can drive up to 8 leds, with two programmable +DIM modes; it could even be used as a gpio expander but this driver assumes it +is used as a led controller. + +The DIM modes are used to set _blink_ patterns for leds, the pattern is +specified supplying two parameters: + - period: from 0s to 1.6s + - duty cycle: percentage of the period the led is on, from 0 to 100 + +Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern. +See the datasheet for details. + +LP3944 can be found on Motorola A910 smartphone, where it drives the rgb +leds, the camera flash light and the lcds power. + + +Notes +----- +The chip is used mainly in embedded contexts, so this driver expects it is +registered using the i2c_board_info mechanism. + +To register the chip at address 0x60 on adapter 0, set the platform data +according to include/linux/leds-lp3944.h, set the i2c board info: + + static struct i2c_board_info __initdata a910_i2c_board_info[] = { + { + I2C_BOARD_INFO("lp3944", 0x60), + .platform_data = &a910_lp3944_leds, + }, + }; + +and register it in the platform init function + + i2c_register_board_info(0, a910_i2c_board_info, + ARRAY_SIZE(a910_i2c_board_info)); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index cfcd6bf831c9b..7c8e7122aaa90 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -146,6 +146,17 @@ config LEDS_GPIO_OF of_platform devices. For instance, LEDs which are listed in a "dts" file. +config LEDS_LP3944 + tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" + depends on LEDS_CLASS && I2C + help + This option enables support for LEDs connected to the National + Semiconductor LP3944 Lighting Management Unit (LMU) also known as + Fun Light Chip. + + To compile this driver as a module, choose M here: the + module will be called leds-lp3944. + config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook" depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 2d41c4dcf92ff..e8cdcf77a4c35 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o +obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_FSG) += leds-fsg.o diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c new file mode 100644 index 0000000000000..5946208ba26e5 --- /dev/null +++ b/drivers/leds/leds-lp3944.c @@ -0,0 +1,466 @@ +/* + * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip + * + * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +/* + * I2C driver for National Semiconductor LP3944 Funlight Chip + * http://www.national.com/pf/LP/LP3944.html + * + * This helper chip can drive up to 8 leds, with two programmable DIM modes; + * it could even be used as a gpio expander but this driver assumes it is used + * as a led controller. + * + * The DIM modes are used to set _blink_ patterns for leds, the pattern is + * specified supplying two parameters: + * - period: from 0s to 1.6s + * - duty cycle: percentage of the period the led is on, from 0 to 100 + * + * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb + * leds, the camera flash light and the displays backlights. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/leds.h> +#include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/leds-lp3944.h> + +/* Read Only Registers */ +#define LP3944_REG_INPUT1 0x00 /* LEDs 0-7 InputRegister (Read Only) */ +#define LP3944_REG_REGISTER1 0x01 /* None (Read Only) */ + +#define LP3944_REG_PSC0 0x02 /* Frequency Prescaler 0 (R/W) */ +#define LP3944_REG_PWM0 0x03 /* PWM Register 0 (R/W) */ +#define LP3944_REG_PSC1 0x04 /* Frequency Prescaler 1 (R/W) */ +#define LP3944_REG_PWM1 0x05 /* PWM Register 1 (R/W) */ +#define LP3944_REG_LS0 0x06 /* LEDs 0-3 Selector (R/W) */ +#define LP3944_REG_LS1 0x07 /* LEDs 4-7 Selector (R/W) */ + +/* These registers are not used to control leds in LP3944, they can store + * arbitrary values which the chip will ignore. + */ +#define LP3944_REG_REGISTER8 0x08 +#define LP3944_REG_REGISTER9 0x09 + +#define LP3944_DIM0 0 +#define LP3944_DIM1 1 + +/* period in ms */ +#define LP3944_PERIOD_MIN 0 +#define LP3944_PERIOD_MAX 1600 + +/* duty cycle is a percentage */ +#define LP3944_DUTY_CYCLE_MIN 0 +#define LP3944_DUTY_CYCLE_MAX 100 + +#define ldev_to_led(c) container_of(c, struct lp3944_led_data, ldev) + +/* Saved data */ +struct lp3944_led_data { + u8 id; + enum lp3944_type type; + enum lp3944_status status; + struct led_classdev ldev; + struct i2c_client *client; + struct work_struct work; +}; + +struct lp3944_data { + struct mutex lock; + struct i2c_client *client; + struct lp3944_led_data leds[LP3944_LEDS_MAX]; +}; + +static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value) +{ + int tmp; + + tmp = i2c_smbus_read_byte_data(client, reg); + if (tmp < 0) + return -EINVAL; + + *value = tmp; + + return 0; +} + +static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/** + * Set the period for DIM status + * + * @client: the i2c client + * @dim: either LP3944_DIM0 or LP3944_DIM1 + * @period: period of a blink, that is a on/off cycle, expressed in ms. + */ +static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period) +{ + u8 psc_reg; + u8 psc_value; + int err; + + if (dim == LP3944_DIM0) + psc_reg = LP3944_REG_PSC0; + else if (dim == LP3944_DIM1) + psc_reg = LP3944_REG_PSC1; + else + return -EINVAL; + + /* Convert period to Prescaler value */ + if (period > LP3944_PERIOD_MAX) + return -EINVAL; + + psc_value = (period * 255) / LP3944_PERIOD_MAX; + + err = lp3944_reg_write(client, psc_reg, psc_value); + + return err; +} + +/** + * Set the duty cycle for DIM status + * + * @client: the i2c client + * @dim: either LP3944_DIM0 or LP3944_DIM1 + * @duty_cycle: percentage of a period during which a led is ON + */ +static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim, + u8 duty_cycle) +{ + u8 pwm_reg; + u8 pwm_value; + int err; + + if (dim == LP3944_DIM0) + pwm_reg = LP3944_REG_PWM0; + else if (dim == LP3944_DIM1) + pwm_reg = LP3944_REG_PWM1; + else + return -EINVAL; + + /* Convert duty cycle to PWM value */ + if (duty_cycle > LP3944_DUTY_CYCLE_MAX) + return -EINVAL; + + pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX; + + err = lp3944_reg_write(client, pwm_reg, pwm_value); + + return err; +} + +/** + * Set the led status + * + * @led: a lp3944_led_data structure + * @status: one of LP3944_LED_STATUS_OFF + * LP3944_LED_STATUS_ON + * LP3944_LED_STATUS_DIM0 + * LP3944_LED_STATUS_DIM1 + */ +static int lp3944_led_set(struct lp3944_led_data *led, u8 status) +{ + struct lp3944_data *data = i2c_get_clientdata(led->client); + u8 id = led->id; + u8 reg; + u8 val = 0; + int err; + + dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n", + __func__, led->ldev.name, status); + + switch (id) { + case LP3944_LED0: + case LP3944_LED1: + case LP3944_LED2: + case LP3944_LED3: + reg = LP3944_REG_LS0; + break; + case LP3944_LED4: + case LP3944_LED5: + case LP3944_LED6: + case LP3944_LED7: + id -= LP3944_LED4; + reg = LP3944_REG_LS1; + break; + default: + return -EINVAL; + } + + if (status > LP3944_LED_STATUS_DIM1) + return -EINVAL; + + /* invert only 0 and 1, leave unchanged the other values, + * remember we are abusing status to set blink patterns + */ + if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2) + status = 1 - status; + + mutex_lock(&data->lock); + lp3944_reg_read(led->client, reg, &val); + + val &= ~(LP3944_LED_STATUS_MASK << (id << 1)); + val |= (status << (id << 1)); + + dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n", + __func__, led->ldev.name, reg, id, status, val); + + /* set led status */ + err = lp3944_reg_write(led->client, reg, val); + mutex_unlock(&data->lock); + + return err; +} + +static int lp3944_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct lp3944_led_data *led = ldev_to_led(led_cdev); + u16 period; + u8 duty_cycle; + int err; + + /* units are in ms */ + if (*delay_on + *delay_off > LP3944_PERIOD_MAX) + return -EINVAL; + + if (*delay_on == 0 && *delay_off == 0) { + /* Special case: the leds subsystem requires a default user + * friendly blink pattern for the LED. Let's blink the led + * slowly (1Hz). + */ + *delay_on = 500; + *delay_off = 500; + } + + period = (*delay_on) + (*delay_off); + + /* duty_cycle is the percentage of period during which the led is ON */ + duty_cycle = 100 * (*delay_on) / period; + + /* invert duty cycle for inverted leds, this has the same effect of + * swapping delay_on and delay_off + */ + if (led->type == LP3944_LED_TYPE_LED_INVERTED) + duty_cycle = 100 - duty_cycle; + + /* NOTE: using always the first DIM mode, this means that all leds + * will have the same blinking pattern. + * + * We could find a way later to have two leds blinking in hardware + * with different patterns at the same time, falling back to software + * control for the other ones. + */ + err = lp3944_dim_set_period(led->client, LP3944_DIM0, period); + if (err) + return err; + + err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle); + if (err) + return err; + + dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n", + __func__); + + led->status = LP3944_LED_STATUS_DIM0; + schedule_work(&led->work); + + return 0; +} + +static void lp3944_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct lp3944_led_data *led = ldev_to_led(led_cdev); + + dev_dbg(&led->client->dev, "%s: %s, %d\n", + __func__, led_cdev->name, brightness); + + led->status = brightness; + schedule_work(&led->work); +} + +static void lp3944_led_work(struct work_struct *work) +{ + struct lp3944_led_data *led; + + led = container_of(work, struct lp3944_led_data, work); + lp3944_led_set(led, led->status); +} + +static int lp3944_configure(struct i2c_client *client, + struct lp3944_data *data, + struct lp3944_platform_data *pdata) +{ + int i, err = 0; + + for (i = 0; i < pdata->leds_size; i++) { + struct lp3944_led *pled = &pdata->leds[i]; + struct lp3944_led_data *led = &data->leds[i]; + led->client = client; + led->id = i; + + switch (pled->type) { + + case LP3944_LED_TYPE_LED: + case LP3944_LED_TYPE_LED_INVERTED: + led->type = pled->type; + led->status = pled->status; + led->ldev.name = pled->name; + led->ldev.max_brightness = 1; + led->ldev.brightness_set = lp3944_led_set_brightness; + led->ldev.blink_set = lp3944_led_set_blink; + led->ldev.flags = LED_CORE_SUSPENDRESUME; + + INIT_WORK(&led->work, lp3944_led_work); + err = led_classdev_register(&client->dev, &led->ldev); + if (err < 0) { + dev_err(&client->dev, + "couldn't register LED %s\n", + led->ldev.name); + goto exit; + } + + /* to expose the default value to userspace */ + led->ldev.brightness = led->status; + + /* Set the default led status */ + err = lp3944_led_set(led, led->status); + if (err < 0) { + dev_err(&client->dev, + "%s couldn't set STATUS %d\n", + led->ldev.name, led->status); + goto exit; + } + break; + + case LP3944_LED_TYPE_NONE: + default: + break; + + } + } + return 0; + +exit: + if (i > 0) + for (i = i - 1; i >= 0; i--) + switch (pdata->leds[i].type) { + + case LP3944_LED_TYPE_LED: + case LP3944_LED_TYPE_LED_INVERTED: + led_classdev_unregister(&data->leds[i].ldev); + cancel_work_sync(&data->leds[i].work); + break; + + case LP3944_LED_TYPE_NONE: + default: + break; + } + + return err; +} + +static int __devinit lp3944_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; + struct lp3944_data *data; + + if (lp3944_pdata == NULL) { + dev_err(&client->dev, "no platform data\n"); + return -EINVAL; + } + + /* Let's see whether this adapter can support what we need. */ + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "insufficient functionality!\n"); + return -ENODEV; + } + + data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); + + dev_info(&client->dev, "lp3944 enabled\n"); + + lp3944_configure(client, data, lp3944_pdata); + return 0; +} + +static int __devexit lp3944_remove(struct i2c_client *client) +{ + struct lp3944_platform_data *pdata = client->dev.platform_data; + struct lp3944_data *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < pdata->leds_size; i++) + switch (data->leds[i].type) { + case LP3944_LED_TYPE_LED: + case LP3944_LED_TYPE_LED_INVERTED: + led_classdev_unregister(&data->leds[i].ldev); + cancel_work_sync(&data->leds[i].work); + break; + + case LP3944_LED_TYPE_NONE: + default: + break; + } + + kfree(data); + i2c_set_clientdata(client, NULL); + + return 0; +} + +/* lp3944 i2c driver struct */ +static const struct i2c_device_id lp3944_id[] = { + {"lp3944", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lp3944_id); + +static struct i2c_driver lp3944_driver = { + .driver = { + .name = "lp3944", + }, + .probe = lp3944_probe, + .remove = __devexit_p(lp3944_remove), + .id_table = lp3944_id, +}; + +static int __init lp3944_module_init(void) +{ + return i2c_add_driver(&lp3944_driver); +} + +static void __exit lp3944_module_exit(void) +{ + i2c_del_driver(&lp3944_driver); +} + +module_init(lp3944_module_init); +module_exit(lp3944_module_exit); + +MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); +MODULE_DESCRIPTION("LP3944 Fun Light Chip"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds-lp3944.h b/include/linux/leds-lp3944.h new file mode 100644 index 0000000000000..afc9f9fd70f51 --- /dev/null +++ b/include/linux/leds-lp3944.h @@ -0,0 +1,53 @@ +/* + * leds-lp3944.h - platform data structure for lp3944 led controller + * + * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __LINUX_LEDS_LP3944_H +#define __LINUX_LEDS_LP3944_H + +#include <linux/leds.h> +#include <linux/workqueue.h> + +#define LP3944_LED0 0 +#define LP3944_LED1 1 +#define LP3944_LED2 2 +#define LP3944_LED3 3 +#define LP3944_LED4 4 +#define LP3944_LED5 5 +#define LP3944_LED6 6 +#define LP3944_LED7 7 +#define LP3944_LEDS_MAX 8 + +#define LP3944_LED_STATUS_MASK 0x03 +enum lp3944_status { + LP3944_LED_STATUS_OFF = 0x0, + LP3944_LED_STATUS_ON = 0x1, + LP3944_LED_STATUS_DIM0 = 0x2, + LP3944_LED_STATUS_DIM1 = 0x3 +}; + +enum lp3944_type { + LP3944_LED_TYPE_NONE, + LP3944_LED_TYPE_LED, + LP3944_LED_TYPE_LED_INVERTED, +}; + +struct lp3944_led { + char *name; + enum lp3944_type type; + enum lp3944_status status; +}; + +struct lp3944_platform_data { + struct lp3944_led leds[LP3944_LEDS_MAX]; + u8 leds_size; +}; + +#endif /* __LINUX_LEDS_LP3944_H */ -- GitLab From ed88bae6918fa990cbfe47316bd0f790121aaf00 Mon Sep 17 00:00:00 2001 From: Trent Piepho <xyzzy@speakeasy.org> Date: Tue, 12 May 2009 15:33:12 -0700 Subject: [PATCH 0098/1002] leds: Add options to have GPIO LEDs start on or keep their state There already is a "default-on" trigger but there are problems with it. For one, it's a inefficient way to do it and requires led trigger support to be compiled in. But the real reason is that is produces a glitch on the LED. The GPIO is allocate with the LED *off*, then *later* when the trigger runs it is turned back on. If the LED was already on via the GPIO's reset default or action of the firmware, this produces a glitch where the LED goes from on to off to on. While normally this is fast enough that it wouldn't be noticeable to a human observer, there are still serious problems. One is that there may be something else on the GPIO line, like a hardware alarm or watchdog, that is fast enough to notice the glitch. Another is that the kernel may panic before the LED is turned back on, thus hanging with the LED in the wrong state. This is not just speculation, but actually happened to me with an embedded system that has an LED which should turn off when the kernel finishes booting, which was left in the incorrect state due to a bug in the OF LED binding code. We also let GPIO LEDs get their initial value from whatever the current state of the GPIO line is. On some systems the LEDs are put into some state by the firmware or hardware before Linux boots, and it is desired to have them keep this state which is otherwise unknown to Linux. This requires that the underlying GPIO driver support reading the value of output GPIOs. Some drivers support this and some do not. The platform device binding gains a field in the platform data "default_state" that controls this. There are three constants defined to select from on, off, or keeping the current state. The OpenFirmware binding uses a property named "default-state" that can be set to "on", "off", or "keep". The default if the property isn't present is off. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Acked-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Wolfram Sang <w.sang@pengutronix.de> Acked-by: Sean MacLennan <smaclennan@pikatech.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- .../powerpc/dts-bindings/gpio/led.txt | 17 +++++++++++++++- drivers/leds/leds-gpio.c | 20 ++++++++++++++++--- include/linux/leds.h | 9 +++++++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Documentation/powerpc/dts-bindings/gpio/led.txt b/Documentation/powerpc/dts-bindings/gpio/led.txt index 4fe14deedc0a3..064db928c3c12 100644 --- a/Documentation/powerpc/dts-bindings/gpio/led.txt +++ b/Documentation/powerpc/dts-bindings/gpio/led.txt @@ -16,10 +16,17 @@ LED sub-node properties: string defining the trigger assigned to the LED. Current triggers are: "backlight" - LED will act as a back-light, controlled by the framebuffer system - "default-on" - LED will turn on + "default-on" - LED will turn on, but see "default-state" below "heartbeat" - LED "double" flashes at a load average based rate "ide-disk" - LED indicates disk activity "timer" - LED flashes at a fixed, configurable rate +- default-state: (optional) The initial state of the LED. Valid + values are "on", "off", and "keep". If the LED is already on or off + and the default-state property is set the to same value, then no + glitch should be produced where the LED momentarily turns off (or + on). The "keep" setting will keep the LED at whatever its current + state is, without producing a glitch. The default is off if this + property is not present. Examples: @@ -30,14 +37,22 @@ leds { gpios = <&mcu_pio 0 1>; /* Active low */ linux,default-trigger = "ide-disk"; }; + + fault { + gpios = <&mcu_pio 1 0>; + /* Keep LED on if BIOS detected hardware fault */ + default-state = "keep"; + }; }; run-control { compatible = "gpio-leds"; red { gpios = <&mpc8572 6 0>; + default-state = "off"; }; green { gpios = <&mpc8572 7 0>; + default-state = "on"; }; } diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 76895e691042d..6b06638eb5b42 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -76,7 +76,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, struct gpio_led_data *led_dat, struct device *parent, int (*blink_set)(unsigned, unsigned long *, unsigned long *)) { - int ret; + int ret, state; /* skip leds that aren't available */ if (!gpio_is_valid(template->gpio)) { @@ -99,11 +99,15 @@ static int __devinit create_gpio_led(const struct gpio_led *template, led_dat->cdev.blink_set = gpio_blink_set; } led_dat->cdev.brightness_set = gpio_led_set; - led_dat->cdev.brightness = LED_OFF; + if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) + state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low; + else + state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); + led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; if (!template->retain_state_suspended) led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; - ret = gpio_direction_output(led_dat->gpio, led_dat->active_low); + ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); if (ret < 0) goto err; @@ -223,12 +227,22 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, memset(&led, 0, sizeof(led)); for_each_child_of_node(np, child) { enum of_gpio_flags flags; + const char *state; led.gpio = of_get_gpio_flags(child, 0, &flags); led.active_low = flags & OF_GPIO_ACTIVE_LOW; led.name = of_get_property(child, "label", NULL) ? : child->name; led.default_trigger = of_get_property(child, "linux,default-trigger", NULL); + state = of_get_property(child, "default-state", NULL); + if (state) { + if (!strcmp(state, "keep")) + led.default_state = LEDS_GPIO_DEFSTATE_KEEP; + else if(!strcmp(state, "on")) + led.default_state = LEDS_GPIO_DEFSTATE_ON; + else + led.default_state = LEDS_GPIO_DEFSTATE_OFF; + } ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], &ofdev->dev, NULL); diff --git a/include/linux/leds.h b/include/linux/leds.h index c7f0b148df060..62af62915cf75 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -143,9 +143,14 @@ struct gpio_led { const char *name; const char *default_trigger; unsigned gpio; - u8 active_low : 1; - u8 retain_state_suspended : 1; + unsigned active_low : 1; + unsigned retain_state_suspended : 1; + unsigned default_state : 2; + /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ }; +#define LEDS_GPIO_DEFSTATE_OFF 0 +#define LEDS_GPIO_DEFSTATE_ON 1 +#define LEDS_GPIO_DEFSTATE_KEEP 2 struct gpio_led_platform_data { int num_leds; -- GitLab From a1dd8c617217322614f0465ae347895c4b58e1ab Mon Sep 17 00:00:00 2001 From: Richard Purdie <rpurdie@linux.intel.com> Date: Mon, 22 Jun 2009 14:54:13 +0100 Subject: [PATCH 0099/1002] leds: Futher document blink_set Futher document blink_set function pointer Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- include/linux/leds.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/leds.h b/include/linux/leds.h index 62af62915cf75..d8bf9665e70cc 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -47,7 +47,8 @@ struct led_classdev { /* Activate hardware accelerated blink, delays are in * miliseconds and if none is provided then a sensible default - * should be chosen. */ + * should be chosen. The call can adjust the timings if it can't + * match the values specified exactly. */ int (*blink_set)(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off); -- GitLab From 1d469c6c38c9deaa1836d2c1955330944719e4ef Mon Sep 17 00:00:00 2001 From: Aviv Laufer <aviv.laufer@gmail.com> Date: Tue, 23 Jun 2009 16:28:36 +0300 Subject: [PATCH 0100/1002] backlight: Fix tdo24m crash on kmalloc There is a crash in tdo24m module caused by a call to kmalloc with the second parameter sizeof(flag) instead of flag. Signed-off-by: Aviv Laufer <aviv.laufer@gmail.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com> --- drivers/video/backlight/tdo24m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 1dae7f8f3c6b4..51422fc4f6060 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -356,7 +356,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi) lcd->power = FB_BLANK_POWERDOWN; lcd->mode = MODE_VGA; /* default to VGA */ - lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL)); + lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL); if (lcd->buf == NULL) { kfree(lcd); return -ENOMEM; -- GitLab From cca03c0aeb18a975abec28df518a2b64ae3e6964 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Tue, 23 Jun 2009 17:12:49 +0530 Subject: [PATCH 0101/1002] perf stat: Fix verbose for perf stat Error message should use stderr for verbose (-v), otherwise message will be lost for: $ ./perf stat -v <cmd> > /dev/null For example on AMD bus-cycles event is not available so now it looks like: $ ./perf stat -v -e bus-cycles ls > /dev/null Error: counter 0, sys_perf_counter_open() syscall returned with -1 (Invalid argument) Performance counter stats for 'ls': <not counted> bus-cycles 0.006765877 seconds time elapsed. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245757369.3776.1.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 6d3eeac1ea257..5e04fcc8d0776 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -109,6 +109,10 @@ static u64 walltime_nsecs_noise; static u64 runtime_cycles_avg; static u64 runtime_cycles_noise; + +#define ERR_PERF_OPEN \ +"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" + static void create_perf_stat_counter(int counter) { struct perf_counter_attr *attr = attrs + counter; @@ -119,20 +123,20 @@ static void create_perf_stat_counter(int counter) if (system_wide) { int cpu; - for (cpu = 0; cpu < nr_cpus; cpu ++) { + for (cpu = 0; cpu < nr_cpus; cpu++) { fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); - if (fd[cpu][counter] < 0 && verbose) { - printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno)); - } + if (fd[cpu][counter] < 0 && verbose) + fprintf(stderr, ERR_PERF_OPEN, counter, + fd[cpu][counter], strerror(errno)); } } else { attr->inherit = inherit; attr->disabled = 1; fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); - if (fd[0][counter] < 0 && verbose) { - printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno)); - } + if (fd[0][counter] < 0 && verbose) + fprintf(stderr, ERR_PERF_OPEN, counter, + fd[0][counter], strerror(errno)); } } @@ -168,7 +172,7 @@ static void read_counter(int counter) count[0] = count[1] = count[2] = 0; nv = scale ? 3 : 1; - for (cpu = 0; cpu < nr_cpus; cpu ++) { + for (cpu = 0; cpu < nr_cpus; cpu++) { if (fd[cpu][counter] < 0) continue; -- GitLab From 7262b6e4a4cc18d0f67df145d032c843e4bc382b Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Tue, 23 Jun 2009 12:40:54 +0900 Subject: [PATCH 0102/1002] x86, mce: Fix mce resume on 32bit Calling mcheck_init() on resume is required only with CONFIG_X86_OLD_MCE=y. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Acked-by: Andi Kleen <andi@firstfloor.org> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/power/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index d277ef1eea511..b3d20b9cac636 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -244,7 +244,7 @@ static void __restore_processor_state(struct saved_context *ctxt) do_fpu_end(); mtrr_ap_init(); -#ifdef CONFIG_X86_32 +#ifdef CONFIG_X86_OLD_MCE mcheck_init(&boot_cpu_data); #endif } -- GitLab From 76609a6928bff29ca05a94420ae3e088fbb9c2f9 Mon Sep 17 00:00:00 2001 From: Nelson Castillo <arhuaco@freaks-unidos.net> Date: Tue, 23 Jun 2009 13:54:32 -0500 Subject: [PATCH 0103/1002] [ARM] GTA02: build fixes (s3c2410_nand_set usage) This patch fixes two errors we get when building GTA02 kernel. ~ use_bbt is incorrect, we need flash_bbt. ~ We do not need .force_soft_ecc because we can unset CONFIG_MTD_NAND_S3C2410_HWECC. Signed-off-by: Nelson Castillo <arhuaco@freaks-unidos.net> [ben-linux@fluff.org: updated patch description] Signed-off-by: Ben Dooks <ben-linux@fluff.org> --- arch/arm/mach-s3c2442/mach-gta02.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index e23b581aa0e16..0fb385bd9cd9c 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -433,8 +433,7 @@ static struct s3c2410_nand_set gta02_nand_sets[] = { */ .name = "neo1973-nand", .nr_chips = 1, - .use_bbt = 1, - .force_soft_ecc = 1, + .flash_bbt = 1, }, }; -- GitLab From f92e93eb5f4d56d73215f089580d53597bacd468 Mon Sep 17 00:00:00 2001 From: Jerome Glisse <jglisse@redhat.com> Date: Mon, 22 Jun 2009 18:15:58 +0200 Subject: [PATCH 0104/1002] drm/radeon: fix radeon kms framebuffer device smem.start is a physical address which kernel can remap to access video memory of the fb buffer. We now pin the fb buffer into vram by doing so we are loosing vram but fbdev need to be reworked to allow change in framebuffer address. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@linux.ie> --- drivers/gpu/drm/radeon/radeon_device.c | 4 ---- drivers/gpu/drm/radeon/radeon_fb.c | 27 ++++++++++++++++------- drivers/gpu/drm/radeon/radeon_object.c | 30 -------------------------- 3 files changed, 19 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f30aa7274a540..3f48a57531b58 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -496,7 +496,6 @@ int radeon_device_init(struct radeon_device *rdev, radeon_errata(rdev); /* Initialize scratch registers */ radeon_scratch_init(rdev); - /* TODO: disable VGA need to use VGA request */ /* BIOS*/ if (!radeon_get_bios(rdev)) { @@ -604,9 +603,6 @@ int radeon_device_init(struct radeon_device *rdev, if (r) { return r; } - if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { - rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; - } if (!ret) { DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fa86d398945e2..09987089193e2 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev, { struct fb_info *info; struct radeon_fb_device *rfbdev; - struct drm_framebuffer *fb; + struct drm_framebuffer *fb = NULL; struct radeon_framebuffer *rfb; struct drm_mode_fb_cmd mode_cmd; struct drm_gem_object *gobj = NULL; struct radeon_object *robj = NULL; struct device *device = &rdev->pdev->dev; int size, aligned_size, ret; + u64 fb_gpuaddr; void *fbptr = NULL; + unsigned long tmp; mode_cmd.width = surface_width; mode_cmd.height = surface_height; @@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev, aligned_size = ALIGN(size, PAGE_SIZE); ret = radeon_gem_object_create(rdev, aligned_size, 0, - RADEON_GEM_DOMAIN_VRAM, - false, ttm_bo_type_kernel, - false, &gobj); + RADEON_GEM_DOMAIN_VRAM, + false, ttm_bo_type_kernel, + false, &gobj); if (ret) { - printk(KERN_ERR "failed to allocate framebuffer\n"); + printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", + surface_width, surface_height); ret = -ENOMEM; goto out; } @@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev, ret = -ENOMEM; goto out_unref; } + ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); + if (ret) { + printk(KERN_ERR "failed to pin framebuffer\n"); + ret = -ENOMEM; + goto out_unref; + } list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); rfb = to_radeon_framebuffer(fb); *rfb_p = rfb; rdev->fbdev_rfb = rfb; + rdev->fbdev_robj = robj; info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); if (info == NULL) { @@ -546,8 +556,8 @@ int radeonfb_create(struct radeon_device *rdev, info->flags = FBINFO_DEFAULT; info->fbops = &radeonfb_ops; info->fix.line_length = fb->pitch; - info->screen_base = fbptr; - info->fix.smem_start = (unsigned long)fbptr; + tmp = fb_gpuaddr - rdev->mc.vram_location; + info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = size; info->screen_base = fbptr; info->screen_size = size; @@ -644,7 +654,7 @@ int radeonfb_create(struct radeon_device *rdev, if (robj) { radeon_object_kunmap(robj); } - if (ret) { + if (fb && ret) { list_del(&fb->filp_head); drm_gem_object_unreference(gobj); drm_framebuffer_cleanup(fb); @@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) robj = rfb->obj->driver_private; unregister_framebuffer(info); radeon_object_kunmap(robj); + radeon_object_unpin(robj); framebuffer_release(info); } diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 983e8df5e000d..bac0d06c52ace 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, { uint32_t flags; uint32_t tmp; - void *fbptr; int r; flags = radeon_object_flags_from_domain(domain); @@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); return r; } - if (robj->rdev->fbdev_robj == robj) { - mutex_lock(&robj->rdev->fbdev_info->lock); - radeon_object_kunmap(robj); - } tmp = robj->tobj.mem.placement; ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; @@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, DRM_ERROR("radeon: failed to pin object.\n"); } radeon_object_unreserve(robj); - if (robj->rdev->fbdev_robj == robj) { - if (!r) { - r = radeon_object_kmap(robj, &fbptr); - } - if (!r) { - robj->rdev->fbdev_info->screen_base = fbptr; - robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; - } - mutex_unlock(&robj->rdev->fbdev_info->lock); - } return r; } void radeon_object_unpin(struct radeon_object *robj) { uint32_t flags; - void *fbptr; int r; spin_lock(&robj->tobj.lock); @@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj) DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); return; } - if (robj->rdev->fbdev_robj == robj) { - mutex_lock(&robj->rdev->fbdev_info->lock); - radeon_object_kunmap(robj); - } flags = robj->tobj.mem.placement; robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; r = ttm_buffer_object_validate(&robj->tobj, @@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj) DRM_ERROR("radeon: failed to unpin buffer.\n"); } radeon_object_unreserve(robj); - if (robj->rdev->fbdev_robj == robj) { - if (!r) { - r = radeon_object_kmap(robj, &fbptr); - } - if (!r) { - robj->rdev->fbdev_info->screen_base = fbptr; - robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; - } - mutex_unlock(&robj->rdev->fbdev_info->lock); - } } int radeon_object_wait(struct radeon_object *robj) -- GitLab From 696d4df1dbfe0b054e94c1990b49c1727ffc1ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <daenzer@vmware.com> Date: Tue, 23 Jun 2009 16:12:53 +0200 Subject: [PATCH 0105/1002] drm/radeon: Don't initialize acceleration related fields of struct fb_info. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Might lure userspace into trying silly things otherwise. Signed-off-by: Michel Dänzer <daenzer@vmware.com> Signed-off-by: Dave Airlie <airlied@linux.ie> --- drivers/gpu/drm/radeon/radeon_fb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 09987089193e2..9e8f191eb64a2 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -551,7 +551,7 @@ int radeonfb_create(struct radeon_device *rdev, info->fix.xpanstep = 1; /* doing it in hw */ info->fix.ypanstep = 1; /* doing it in hw */ info->fix.ywrapstep = 0; - info->fix.accel = FB_ACCEL_I830; + info->fix.accel = FB_ACCEL_NONE; info->fix.type_aux = 0; info->flags = FBINFO_DEFAULT; info->fbops = &radeonfb_ops; @@ -572,8 +572,8 @@ int radeonfb_create(struct radeon_device *rdev, info->var.width = -1; info->var.xres = fb_width; info->var.yres = fb_height; - info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); - info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); + info->fix.mmio_start = 0; + info->fix.mmio_len = 0; info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; -- GitLab From b1e3a6d1c4d0ac75ad8289bcfd69efcc9b1bc6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <daenzer@vmware.com> Date: Tue, 23 Jun 2009 16:12:54 +0200 Subject: [PATCH 0106/1002] drm/radeon: Clear surface registers at initialization time. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some PowerMac firmwares set up a tiling surface at the beginning of VRAM which messes us up otherwise. Signed-off-by: Michel Dänzer <daenzer@vmware.com> Signed-off-by: Dave Airlie <airlied@linux.ie> --- drivers/gpu/drm/radeon/radeon_device.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 3f48a57531b58..f97563db4e595 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -34,6 +34,23 @@ #include "radeon_asic.h" #include "atom.h" +/* + * Clear GPU surface registers. + */ +static void radeon_surface_init(struct radeon_device *rdev) +{ + /* FIXME: check this out */ + if (rdev->family < CHIP_R600) { + int i; + + for (i = 0; i < 8; i++) { + WREG32(RADEON_SURFACE0_INFO + + i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), + 0); + } + } +} + /* * GPU scratch registers helpers function. */ @@ -496,6 +513,9 @@ int radeon_device_init(struct radeon_device *rdev, radeon_errata(rdev); /* Initialize scratch registers */ radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ /* BIOS*/ if (!radeon_get_bios(rdev)) { -- GitLab From e14cbee401cd00779a5267128371506b22c77bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel@daenzer.net> Date: Tue, 23 Jun 2009 12:36:32 +0200 Subject: [PATCH 0107/1002] drm: Fix shifts which were miscalculated when converting from bitfields. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like I managed to mess up most shifts when converting from bitfields. :( The patch below works on my Thinkpad T500 (as well as on my PowerBook, where the previous change worked as well, maybe out of luck...). I'd appreciate more testing and eyes looking over it though. Signed-off-by: Michel Dänzer <daenzer@vmware.com> Tested-by: Michael Pyne <mpyne@kde.org> Signed-off-by: Dave Airlie <airlied@linux.ie> --- drivers/gpu/drm/drm_edid.c | 12 ++++++------ include/drm/drm_edid.h | 38 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7d0835226f6ed..80cc6d06d61b6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -294,10 +294,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; - unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo; - unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo; - unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf); - unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; + unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; + unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; + unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; + unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); /* ignore tiny modes */ if (hactive < 64 || vactive < 64) @@ -347,8 +347,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; - mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; - mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; + mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; + mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; if (quirks & EDID_QUIRK_DETAILED_IN_CM) { mode->width_mm *= 10; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c263e4d717540..7d6c9a2dfcbbb 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -35,11 +35,11 @@ struct est_timings { } __attribute__((packed)); /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ -#define EDID_TIMING_ASPECT_SHIFT 0 +#define EDID_TIMING_ASPECT_SHIFT 6 #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT) /* need to add 60 */ -#define EDID_TIMING_VFREQ_SHIFT 2 +#define EDID_TIMING_VFREQ_SHIFT 0 #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT) struct std_timing { @@ -47,11 +47,11 @@ struct std_timing { u8 vfreq_aspect; } __attribute__((packed)); -#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 6) -#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 5) +#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) +#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) -#define DRM_EDID_PT_STEREO (1 << 2) -#define DRM_EDID_PT_INTERLACED (1 << 1) +#define DRM_EDID_PT_STEREO (1 << 5) +#define DRM_EDID_PT_INTERLACED (1 << 7) /* If detailed data is pixel timing */ struct detailed_pixel_timing { @@ -93,7 +93,7 @@ struct detailed_data_monitor_range { } __attribute__((packed)); struct detailed_data_wpindex { - u8 white_xy_lo; /* Upper 2 bits each */ + u8 white_yx_lo; /* Lower 2 bits each */ u8 white_x_hi; u8 white_y_hi; u8 gamma; /* need to divide by 100 then add 1 */ @@ -135,21 +135,21 @@ struct detailed_timing { } data; } __attribute__((packed)); -#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 7) -#define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 5) -#define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 4) +#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0) +#define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 1) +#define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 2) #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) -#define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 2) -#define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 1) -#define DRM_EDID_INPUT_DIGITAL (1 << 0) /* bits above must be zero if set */ +#define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4) +#define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5) +#define DRM_EDID_INPUT_DIGITAL (1 << 7) /* bits below must be zero if set */ -#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 7) -#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 6) -#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 5) +#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) +#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1) +#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2) #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ -#define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 2) -#define DRM_EDID_FEATURE_PM_SUSPEND (1 << 1) -#define DRM_EDID_FEATURE_PM_STANDBY (1 << 0) +#define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5) +#define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6) +#define DRM_EDID_FEATURE_PM_STANDBY (1 << 7) struct edid { u8 header[8]; -- GitLab From 176f613e60b63f2d77e6c69f036cfc754f3aaac6 Mon Sep 17 00:00:00 2001 From: Jerome Glisse <jglisse@redhat.com> Date: Mon, 22 Jun 2009 18:16:13 +0200 Subject: [PATCH 0108/1002] drm/radeon: fix driver initialization order so radeon kms can be builtin TTM need to be initialized before radeon if KMS is enabled otherwise the kernel will crash hard. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@linux.ie> --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/radeon/radeon_drv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4e89ab08b7b8d..fe23f29f7cba8 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -16,6 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.o obj-$(CONFIG_DRM) += drm.o +obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_TDFX) += tdfx/ obj-$(CONFIG_DRM_R128) += r128/ obj-$(CONFIG_DRM_RADEON)+= radeon/ @@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915) += i915/ obj-$(CONFIG_DRM_SIS) += sis/ obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VIA) +=via/ -obj-$(CONFIG_DRM_TTM) += ttm/ diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 09c9fb9f62107..84ba69f487849 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -345,7 +345,7 @@ static void __exit radeon_exit(void) drm_exit(driver); } -late_initcall(radeon_init); +module_init(radeon_init); module_exit(radeon_exit); MODULE_AUTHOR(DRIVER_AUTHOR); -- GitLab From 8b169b5f1f46da8ece1ce7304cda7155fffe3892 Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Wed, 24 Jun 2009 16:31:50 +1000 Subject: [PATCH 0109/1002] drm: remove unused #include <linux/version.h>'s Remove unused #include <linux/version.h>('s) in drivers/gpu/drm/ttm/ttm_bo_util.c drivers/gpu/drm/ttm/ttm_bo_vm.c drivers/gpu/drm/ttm/ttm_tt.c Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com> --- drivers/gpu/drm/ttm/ttm_bo_util.c | 1 - drivers/gpu/drm/ttm/ttm_bo_vm.c | 1 - drivers/gpu/drm/ttm/ttm_tt.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 517c845596331..bdec583901ebc 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -34,7 +34,6 @@ #include <linux/highmem.h> #include <linux/wait.h> #include <linux/vmalloc.h> -#include <linux/version.h> #include <linux/module.h> void ttm_bo_free_old_node(struct ttm_buffer_object *bo) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 27b146c54fbcb..40b75032ea474 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -32,7 +32,6 @@ #include <ttm/ttm_bo_driver.h> #include <ttm/ttm_placement.h> #include <linux/mm.h> -#include <linux/version.h> #include <linux/rbtree.h> #include <linux/module.h> #include <linux/uaccess.h> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 0331fa74cd3f1..75dc8bd245920 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -28,7 +28,6 @@ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> */ -#include <linux/version.h> #include <linux/vmalloc.h> #include <linux/sched.h> #include <linux/highmem.h> -- GitLab From ffc36c7610731115c77700dcc53901920361c235 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Tue, 23 Jun 2009 03:43:00 -0700 Subject: [PATCH 0110/1002] ide: fix handling of unexpected IRQs vs request_irq() Add ide_host_enable_irqs() helper and use it in ide_host_register() before registering ports. Then remove no longer needed IRQ unmasking from in init_irq(). This should fix the problem with "screaming" shared IRQ on the first port (after request_irq() call while we have the unexpected IRQ pending on the second port) which was uncovered by my rework of the serialized interfaces support. Reported-by: Frans Pop <elendil@planet.nl> Tested-by: Frans Pop <elendil@planet.nl> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-probe.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 51af4eea0d367..1bb106f6221a5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -818,6 +818,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) return j; } +static void ide_host_enable_irqs(struct ide_host *host) +{ + ide_hwif_t *hwif; + int i; + + ide_host_for_each_port(i, hwif, host) { + if (hwif == NULL) + continue; + + /* clear any pending IRQs */ + hwif->tp_ops->read_status(hwif); + + /* unmask IRQs */ + if (hwif->io_ports.ctl_addr) + hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); + } +} + /* * This routine sets up the IRQ for an IDE interface. */ @@ -831,9 +849,6 @@ static int init_irq (ide_hwif_t *hwif) if (irq_handler == NULL) irq_handler = ide_intr; - if (io_ports->ctl_addr) - hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); - if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) goto out_up; @@ -1404,6 +1419,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, ide_port_tune_devices(hwif); } + ide_host_enable_irqs(host); + ide_host_for_each_port(i, hwif, host) { if (hwif == NULL) continue; -- GitLab From af054ed0018f0a69f8ea6f7546cbf34385edf13b Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Tue, 23 Jun 2009 16:01:06 -0700 Subject: [PATCH 0111/1002] ide-cd: Don't warn on bogus block size unless it actually matters. Frans Pop reported that his CDROM drive reports a blocksize of 2352, and this causes new warnings due to commit e8e7b9eb11c34ee18bde8b7011af41938d1ad667 ("ide-cd: fix oops when using growisofs"). What we're trying to do is make sure that "blocklen >> SECTOR_BITS" is something the block layer won't choke on. And for Frans' case "2352 >> SECTOR_BITS" is equal to "2048 >> SECTOR_BITS", and thats "4". So warning in this case gives no real benefit. Reported-by: Frans Pop <elendil@planet.nl> Tested-by: Frans Pop <elendil@planet.nl> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-cd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4a19686fcfe9a..a9a1bfb14e7c7 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -876,9 +876,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, return stat; /* - * Sanity check the given block size + * Sanity check the given block size, in so far as making + * sure the sectors_per_frame we give to the caller won't + * end up being bogus. */ blocklen = be32_to_cpu(capbuf.blocklen); + blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS; switch (blocklen) { case 512: case 1024: -- GitLab From d9ae62433e46909fc9e7d97ce74202c2851667b8 Mon Sep 17 00:00:00 2001 From: Frans Pop <elendil@planet.nl> Date: Tue, 23 Jun 2009 16:02:58 -0700 Subject: [PATCH 0112/1002] ide-cd: Improve "weird block size" error message Currently the error gets repeated too frequently, for example each time HAL polls the device when a disc is present. Avoid that by using printk_once instead of printk. Also join the error and corrective action messages into a single line. Signed-off-by: Frans Pop <elendil@planet.nl> Acked-by: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-cd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index a9a1bfb14e7c7..f0ede5953af8b 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -889,10 +889,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, case 4096: break; default: - printk(KERN_ERR PFX "%s: weird block size %u\n", + printk_once(KERN_ERR PFX "%s: weird block size %u; " + "setting default block size to 2048\n", drive->name, blocklen); - printk(KERN_ERR PFX "%s: default to 2kb block size\n", - drive->name); blocklen = 2048; break; } -- GitLab From 346c17a6cf60375323adfaa4b8a9d841049f890e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Mon, 22 Jun 2009 07:38:26 +0000 Subject: [PATCH 0113/1002] ide: relax DMA info validity checking There are some broken devices that report multiple DMA xfer modes enabled at once (ATA spec doesn't allow it) but otherwise work fine with DMA so just delete ide_id_dma_bug(). [ As discovered by detective work by Frans and Bart, due to how handling of the ID block was handled before commit c419993 ("ide-iops: only clear DMA words on setting DMA mode") this check was always seeing zeros in the fields or other similar garbage. Therefore this check wasn't actually checking anything. Now that the tests actually check the real bits, all we see are devices that trigger the check yet work perfectly fine, therefore killing this useless check is the best thing to do. -DaveM ] Reported-by: Frans Pop <elendil@planet.nl> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-dma.c | 21 --------------------- drivers/ide/ide-iops.c | 3 --- include/linux/ide.h | 2 -- 3 files changed, 26 deletions(-) diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 219e6fb78dc64..ee58c88dee5a6 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -361,9 +361,6 @@ static int ide_tune_dma(ide_drive_t *drive) if (__ide_dma_bad_drive(drive)) return 0; - if (ide_id_dma_bug(drive)) - return 0; - if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) return config_drive_for_dma(drive); @@ -394,24 +391,6 @@ static int ide_dma_check(ide_drive_t *drive) return -1; } -int ide_id_dma_bug(ide_drive_t *drive) -{ - u16 *id = drive->id; - - if (id[ATA_ID_FIELD_VALID] & 4) { - if ((id[ATA_ID_UDMA_MODES] >> 8) && - (id[ATA_ID_MWDMA_MODES] >> 8)) - goto err_out; - } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && - (id[ATA_ID_SWDMA_MODES] >> 8)) - goto err_out; - - return 0; -err_out: - printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); - return 1; -} - int ide_set_dma(ide_drive_t *drive) { int rc; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index fa047150a1c69..917186ec4966c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -329,9 +329,6 @@ int ide_driveid_update(ide_drive_t *drive) kfree(id); - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) - ide_dma_off(drive); - return 1; out_err: if (rc == 2) diff --git a/include/linux/ide.h b/include/linux/ide.h index 95c6e00a72e82..cf1f3888067ca 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1361,7 +1361,6 @@ int ide_in_drive_list(u16 *, const struct drive_list_entry *); #ifdef CONFIG_BLK_DEV_IDEDMA int ide_dma_good_drive(ide_drive_t *); int __ide_dma_bad_drive(ide_drive_t *); -int ide_id_dma_bug(ide_drive_t *); u8 ide_find_dma_mode(ide_drive_t *, u8); @@ -1402,7 +1401,6 @@ void ide_dma_lost_irq(ide_drive_t *); ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int); #else -static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; } static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; } static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } static inline void ide_dma_off_quietly(ide_drive_t *drive) { ; } -- GitLab From ba9413bd284e79ea43b0ae406a7a29526aaf82b3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Tue, 23 Jun 2009 16:11:10 -0700 Subject: [PATCH 0114/1002] ide: add QUANTUM FIREBALLct20 30 with firmware APL.090 to ivb_list[] Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-iops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 917186ec4966c..2892b242bbe1c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -210,6 +210,7 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); */ static const struct drive_list_entry ivb_list[] = { { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, + { "QUANTUM FIREBALLlct20 30" , "APL.0900" }, { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, -- GitLab From a1317f714af7aed60ddc182d0122477cbe36ee9b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Tue, 23 Jun 2009 23:52:17 -0700 Subject: [PATCH 0115/1002] ide: improve handling of Power Management requests Make hwif->rq point to PM request during PM sequence and do not allow any other types of requests to slip in (the old comment was never correct as there should be no such requests generated during PM sequence). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-io.c | 54 ++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1059f809b809b..93b7886a2d6e3 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -476,10 +476,14 @@ void do_ide_request(struct request_queue *q) if (!ide_lock_port(hwif)) { ide_hwif_t *prev_port; - - WARN_ON_ONCE(hwif->rq); repeat: prev_port = hwif->host->cur_port; + + if (drive->dev_flags & IDE_DFLAG_BLOCKED) + rq = hwif->rq; + else + WARN_ON_ONCE(hwif->rq); + if (drive->dev_flags & IDE_DFLAG_SLEEPING && time_after(drive->sleep, jiffies)) { ide_unlock_port(hwif); @@ -506,43 +510,29 @@ void do_ide_request(struct request_queue *q) hwif->cur_dev = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - spin_unlock_irq(&hwif->lock); - spin_lock_irq(q->queue_lock); - /* - * we know that the queue isn't empty, but this can happen - * if the q->prep_rq_fn() decides to kill a request - */ - if (!rq) + if (rq == NULL) { + spin_unlock_irq(&hwif->lock); + spin_lock_irq(q->queue_lock); + /* + * we know that the queue isn't empty, but this can + * happen if ->prep_rq_fn() decides to kill a request + */ rq = blk_fetch_request(drive->queue); + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwif->lock); - spin_unlock_irq(q->queue_lock); - spin_lock_irq(&hwif->lock); - - if (!rq) { - ide_unlock_port(hwif); - goto out; + if (rq == NULL) { + ide_unlock_port(hwif); + goto out; + } } /* * Sanity: don't accept a request that isn't a PM request - * if we are currently power managed. This is very important as - * blk_stop_queue() doesn't prevent the blk_fetch_request() - * above to return us whatever is in the queue. Since we call - * ide_do_request() ourselves, we end up taking requests while - * the queue is blocked... - * - * We let requests forced at head of queue with ide-preempt - * though. I hope that doesn't happen too much, hopefully not - * unless the subdriver triggers such a thing in its own PM - * state machine. + * if we are currently power managed. */ - if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && - blk_pm_request(rq) == 0 && - (rq->cmd_flags & REQ_PREEMPT) == 0) { - /* there should be no pending command at this point */ - ide_unlock_port(hwif); - goto plug_device; - } + BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) && + blk_pm_request(rq) == 0); hwif->rq = rq; -- GitLab From f7679dabfaf69840b000d238a020cee7157aca17 Mon Sep 17 00:00:00 2001 From: Roel Kluin <roel.kluin@gmail.com> Date: Mon, 22 Jun 2009 18:42:33 +0200 Subject: [PATCH 0116/1002] perf_counter tools: Fix strbuf_fread() error path handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit size_t res cannot be less than 0 - fread returns 0 on error. [ Updated by: René Scharfe <rene.scharfe@lsrfire.ath.cx> ] Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Junio C Hamano <gitster@pobox.com> LKML-Reference: <4A3FB479.2090902@lsrfire.ath.cx> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/strbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index eaba093068023..464e7ca898cfe 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -259,7 +259,7 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) res = fread(sb->buf + sb->len, 1, size, f); if (res > 0) strbuf_setlen(sb, sb->len + res); - else if (res < 0 && oldalloc == 0) + else if (oldalloc == 0) strbuf_release(sb); return res; } -- GitLab From c14dab5c0782ef632742963a66276a195418a63c Mon Sep 17 00:00:00 2001 From: Yong Wang <yong.y.wang@linux.intel.com> Date: Wed, 24 Jun 2009 10:13:24 +0800 Subject: [PATCH 0117/1002] perf_counter, x86: Set global control MSR correctly Previous code made an assumption that the power on value of global control MSR has enabled all fixed and general purpose counters properly. However, this is not the case for certain Intel processors, such as Atom - and it might also be firmware dependent. Each enable bit in IA32_PERF_GLOBAL_CTRL is AND'ed with the enable bits for all privilege levels in the respective IA32_PERFEVTSELx or IA32_PERF_FIXED_CTR_CTRL MSRs to start/stop the counting of respective counters. Counting is enabled if the AND'ed results is true; counting is disabled when the result is false. The end result is that all fixed counters are always disabled on Atom processors because the assumption is just invalid. Fix this by not initializing the ctrl-mask out of the global MSR, but setting it to perf_counter_mask. Reported-by: Stephane Eranian <eranian@googlemail.com> Signed-off-by: Yong Wang <yong.y.wang@intel.com> Cc: Arjan van de Ven <arjan@infradead.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20090624021324.GA2788@ywang-moblin2.bj.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/cpu/perf_counter.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 22eb3a1d4f9cd..a310d19faca36 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -969,13 +969,6 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc) if (!x86_pmu.num_counters_fixed) return -1; - /* - * Quirk, IA32_FIXED_CTRs do not work on current Atom processors: - */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && - boot_cpu_data.x86_model == 28) - return -1; - event = hwc->config & ARCH_PERFMON_EVENT_MASK; if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) @@ -1428,8 +1421,6 @@ static int intel_pmu_init(void) */ x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); - rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); - /* * Install the hw-cache-events table: */ @@ -1514,6 +1505,7 @@ void __init init_hw_perf_counters(void) perf_counter_mask |= ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED; + x86_pmu.intel_ctrl = perf_counter_mask; perf_counters_lapic_init(); register_die_notifier(&perf_counter_nmi_notifier); -- GitLab From e1c7e2a6e67fe9db19dd15e71614526a31b5fdb1 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:52:29 +0800 Subject: [PATCH 0118/1002] tracing/events: Don't increment @pos in s_start() While testing syscall tracepoints posted by Jason, I found 3 entries were missing when reading available_events. The output size of available_events is < 4 pages, which means we lost 1 entry per page. The cause is, it's wrong to increment @pos in s_start(). Actually there's another bug here -- reading avaiable_events/set_events can race with module unload: # cat available_events | s_start() | s_stop() | | # rmmod foo.ko s_start() | call = list_entry(m->private) | @call might be freed and accessing it will lead to crash. Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A4186DD.6090405@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_events.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index aa08be69a1b6c..53c8fd376a88a 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -300,10 +300,18 @@ t_next(struct seq_file *m, void *v, loff_t *pos) static void *t_start(struct seq_file *m, loff_t *pos) { + struct ftrace_event_call *call = NULL; + loff_t l; + mutex_lock(&event_mutex); - if (*pos == 0) - m->private = ftrace_events.next; - return t_next(m, NULL, pos); + + m->private = ftrace_events.next; + for (l = 0; l <= *pos; ) { + call = t_next(m, NULL, &l); + if (!call) + break; + } + return call; } static void * @@ -332,10 +340,18 @@ s_next(struct seq_file *m, void *v, loff_t *pos) static void *s_start(struct seq_file *m, loff_t *pos) { + struct ftrace_event_call *call = NULL; + loff_t l; + mutex_lock(&event_mutex); - if (*pos == 0) - m->private = ftrace_events.next; - return s_next(m, NULL, pos); + + m->private = ftrace_events.next; + for (l = 0; l <= *pos; ) { + call = s_next(m, NULL, &l); + if (!call) + break; + } + return call; } static int t_show(struct seq_file *m, void *v) -- GitLab From c8961ec6da22ea010bf4470a8e0fb3fdad0f11c4 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:52:58 +0800 Subject: [PATCH 0119/1002] tracing_bprintk: Don't increment @pos in t_start() It's wrong to increment @pos in t_start(), otherwise we'll lose some entries when reading printk_formats, if the output is larger than PAGE_SIZE. Reported-by: Lai Jiangshan <laijs@cn.fujitsu.com> Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A4186FA.1020106@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_printk.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 9bece9687b62a..7b62781108273 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -155,25 +155,19 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) EXPORT_SYMBOL_GPL(__ftrace_vprintk); static void * -t_next(struct seq_file *m, void *v, loff_t *pos) +t_start(struct seq_file *m, loff_t *pos) { - const char **fmt = m->private; - const char **next = fmt; - - (*pos)++; + const char **fmt = __start___trace_bprintk_fmt + *pos; if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) return NULL; - - next = fmt; - m->private = ++next; - return fmt; } -static void *t_start(struct seq_file *m, loff_t *pos) +static void *t_next(struct seq_file *m, void * v, loff_t *pos) { - return t_next(m, NULL, pos); + (*pos)++; + return t_start(m, pos); } static int t_show(struct seq_file *m, void *v) @@ -224,15 +218,7 @@ static const struct seq_operations show_format_seq_ops = { static int ftrace_formats_open(struct inode *inode, struct file *file) { - int ret; - - ret = seq_open(file, &show_format_seq_ops); - if (!ret) { - struct seq_file *m = file->private_data; - - m->private = __start___trace_bprintk_fmt; - } - return ret; + return seq_open(file, &show_format_seq_ops); } static const struct file_operations ftrace_formats_fops = { -- GitLab From 2961bf345fd1b736c3db46cad0f69855f67fbe9c Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:53:26 +0800 Subject: [PATCH 0120/1002] trace_stat: Don't increment @pos in seq start() It's wrong to increment @pos in stat_seq_start(). It causes some stat entries lost when reading stat file, if the output of the file is larger than PAGE_SIZE. Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A418716.90209@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_stat.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index c00643733f4cc..e66f5e4933423 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c @@ -199,17 +199,13 @@ static void *stat_seq_start(struct seq_file *s, loff_t *pos) mutex_lock(&session->stat_mutex); /* If we are in the beginning of the file, print the headers */ - if (!*pos && session->ts->stat_headers) { - (*pos)++; + if (!*pos && session->ts->stat_headers) return SEQ_START_TOKEN; - } node = rb_first(&session->stat_root); for (i = 0; node && i < *pos; i++) node = rb_next(node); - (*pos)++; - return node; } -- GitLab From f129e965bef40c6153e4fe505f1e408286213424 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:53:44 +0800 Subject: [PATCH 0121/1002] tracing: Reset iterator in t_start() The iterator is m->private, but it's not reset to trace_types in t_start(). If the output is larger than PAGE_SIZE and t_start() is called the 2nd time, things will go wrong. Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A418728.5020506@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 076fa6f0ee480..3bb31006b5cca 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2053,25 +2053,23 @@ static int tracing_open(struct inode *inode, struct file *file) static void * t_next(struct seq_file *m, void *v, loff_t *pos) { - struct tracer *t = m->private; + struct tracer *t = v; (*pos)++; if (t) t = t->next; - m->private = t; - return t; } static void *t_start(struct seq_file *m, loff_t *pos) { - struct tracer *t = m->private; + struct tracer *t; loff_t l = 0; mutex_lock(&trace_types_lock); - for (; t && l < *pos; t = t_next(m, t, &l)) + for (t = trace_types; t && l < *pos; t = t_next(m, t, &l)) ; return t; @@ -2107,18 +2105,10 @@ static struct seq_operations show_traces_seq_ops = { static int show_traces_open(struct inode *inode, struct file *file) { - int ret; - if (tracing_disabled) return -ENODEV; - ret = seq_open(file, &show_traces_seq_ops); - if (!ret) { - struct seq_file *m = file->private_data; - m->private = trace_types; - } - - return ret; + return seq_open(file, &show_traces_seq_ops); } static ssize_t -- GitLab From 85951842a1020669f0a9eb0f0d1853b41341f097 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:54:00 +0800 Subject: [PATCH 0122/1002] ftrace: Don't increment @pos in g_start() It's wrong to increment @pos in g_start(). It causes some entries lost when reading set_graph_function, if the output of the file is larger than PAGE_SIZE. Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A418738.7090401@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/ftrace.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3718d55fb4c37..cde74b9973b72 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2500,32 +2500,31 @@ int ftrace_graph_count; unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; static void * -g_next(struct seq_file *m, void *v, loff_t *pos) +__g_next(struct seq_file *m, loff_t *pos) { unsigned long *array = m->private; - int index = *pos; - - (*pos)++; - if (index >= ftrace_graph_count) + if (*pos >= ftrace_graph_count) return NULL; + return &array[*pos]; +} - return &array[index]; +static void * +g_next(struct seq_file *m, void *v, loff_t *pos) +{ + (*pos)++; + return __g_next(m, pos); } static void *g_start(struct seq_file *m, loff_t *pos) { - void *p = NULL; - mutex_lock(&graph_lock); /* Nothing, tell g_show to print all functions are enabled */ if (!ftrace_graph_count && !*pos) return (void *)1; - p = g_next(m, p, pos); - - return p; + return __g_next(m, pos); } static void g_stop(struct seq_file *m, void *p) -- GitLab From 694ce0a544fba37a60025a6803ee6265be8a2a22 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:54:19 +0800 Subject: [PATCH 0123/1002] ftrace: Don't manipulate @pos in t_start() It's rather confusing that in t_start(), in some cases @pos is incremented, and in some cases it's decremented and then incremented. This patch rewrites t_start() in a much more general way. Thus we fix a bug that if ftrace_filtered == 1, functions have tracer hooks won't be printed, because the branch is always unreachable: static void *t_start(...) { ... if (!p) return t_hash_start(m, pos); return p; } Before: # echo 'sys_open' > /mnt/tracing/set_ftrace_filter # echo 'sys_write:traceon:4' >> /mnt/tracing/set_ftrace_filter sys_open After: # echo 'sys_open' > /mnt/tracing/set_ftrace_filter # echo 'sys_write:traceon:4' >> /mnt/tracing/set_ftrace_filter sys_open sys_write:traceon:count=4 Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A41874B.4090507@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/ftrace.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index cde74b9973b72..dc810208edde8 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1467,8 +1467,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos) iter->pg = iter->pg->next; iter->idx = 0; goto retry; - } else { - iter->idx = -1; } } else { rec = &iter->pg->records[iter->idx++]; @@ -1497,6 +1495,7 @@ static void *t_start(struct seq_file *m, loff_t *pos) { struct ftrace_iterator *iter = m->private; void *p = NULL; + loff_t l; mutex_lock(&ftrace_lock); /* @@ -1508,23 +1507,21 @@ static void *t_start(struct seq_file *m, loff_t *pos) if (*pos > 0) return t_hash_start(m, pos); iter->flags |= FTRACE_ITER_PRINTALL; - (*pos)++; return iter; } if (iter->flags & FTRACE_ITER_HASH) return t_hash_start(m, pos); - if (*pos > 0) { - if (iter->idx < 0) - return p; - (*pos)--; - iter->idx--; + iter->pg = ftrace_pages_start; + iter->idx = 0; + for (l = 0; l <= *pos; ) { + p = t_next(m, p, &l); + if (!p) + break; } - p = t_next(m, p, pos); - - if (!p) + if (!p && iter->flags & FTRACE_ITER_FILTER) return t_hash_start(m, pos); return p; -- GitLab From d82d62444f87e5993af2fa82ed636b2206e052ea Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 09:54:54 +0800 Subject: [PATCH 0124/1002] ftrace: Fix t_hash_start() When the output of set_ftrace_filter is larger than PAGE_SIZE, t_hash_start() will be called the 2nd time, and then we start from the head of a hlist, which is wrong and causes some entries to be outputed twice. The worse is, if the hlist is large enough, reading set_ftrace_filter won't stop but in a dead loop. Reviewed-by: Liming Wang <liming.wang@windriver.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A41876E.2060407@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/ftrace.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index dc810208edde8..71a52c172140f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1417,10 +1417,20 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos) { struct ftrace_iterator *iter = m->private; void *p = NULL; + loff_t l; + + if (!(iter->flags & FTRACE_ITER_HASH)) + *pos = 0; iter->flags |= FTRACE_ITER_HASH; - return t_hash_next(m, p, pos); + iter->hidx = 0; + for (l = 0; l <= *pos; ) { + p = t_hash_next(m, p, &l); + if (!p) + break; + } + return p; } static int t_hash_show(struct seq_file *m, void *v) -- GitLab From 507e123151149e578c9aae33eb876c49824da5f8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 23 Jun 2009 17:38:15 +0200 Subject: [PATCH 0125/1002] timer stats: Optimize by adding quick check to avoid function calls When the kernel is configured with CONFIG_TIMER_STATS but timer stats are runtime disabled we still get calls to __timer_stats_timer_set_start_info which initializes some fields in the corresponding struct timer_list. So add some quick checks in the the timer stats setup functions to avoid function calls to __timer_stats_timer_set_start_info when timer stats are disabled. In an artificial workload that does nothing but playing ping pong with a single tcp packet via loopback this decreases cpu consumption by 1 - 1.5%. This is part of a modified function trace output on SLES11: perl-2497 [00] 28630647177732388 [+ 125]: sk_reset_timer <-tcp_v4_rcv perl-2497 [00] 28630647177732513 [+ 125]: mod_timer <-sk_reset_timer perl-2497 [00] 28630647177732638 [+ 125]: __timer_stats_timer_set_start_info <-mod_timer perl-2497 [00] 28630647177732763 [+ 125]: __mod_timer <-mod_timer perl-2497 [00] 28630647177732888 [+ 125]: __timer_stats_timer_set_start_info <-__mod_timer perl-2497 [00] 28630647177733013 [+ 93]: lock_timer_base <-__mod_timer Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Mustafa Mesanovic <mustafa.mesanovic@de.ibm.com> Cc: Arjan van de Ven <arjan@infradead.org> LKML-Reference: <20090623153811.GA4641@osiris.boeblingen.de.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/hrtimer.h | 5 +++++ include/linux/timer.h | 4 ++++ kernel/time/timer_stats.c | 16 ++++++++-------- kernel/timer.c | 2 ++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 7400900de94a6..54648e625efdf 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -21,6 +21,7 @@ #include <linux/list.h> #include <linux/wait.h> #include <linux/percpu.h> +#include <linux/timer.h> struct hrtimer_clock_base; @@ -447,6 +448,8 @@ extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, static inline void timer_stats_account_hrtimer(struct hrtimer *timer) { + if (likely(!timer->start_pid)) + return; timer_stats_update_stats(timer, timer->start_pid, timer->start_site, timer->function, timer->start_comm, 0); } @@ -456,6 +459,8 @@ extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) { + if (likely(!timer_stats_active)) + return; __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0)); } diff --git a/include/linux/timer.h b/include/linux/timer.h index ccf882eed8f8d..be62ec2ebea54 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -190,6 +190,8 @@ extern unsigned long get_next_timer_interrupt(unsigned long now); */ #ifdef CONFIG_TIMER_STATS +extern int timer_stats_active; + #define TIMER_STATS_FLAG_DEFERRABLE 0x1 extern void init_timer_stats(void); @@ -203,6 +205,8 @@ extern void __timer_stats_timer_set_start_info(struct timer_list *timer, static inline void timer_stats_timer_set_start_info(struct timer_list *timer) { + if (likely(!timer_stats_active)) + return; __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); } diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index c994530d166da..4cde8b9c716f3 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c @@ -96,7 +96,7 @@ static DEFINE_MUTEX(show_mutex); /* * Collection status, active/inactive: */ -static int __read_mostly active; +int __read_mostly timer_stats_active; /* * Beginning/end timestamps of measurement: @@ -242,7 +242,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, struct entry *entry, input; unsigned long flags; - if (likely(!active)) + if (likely(!timer_stats_active)) return; lock = &per_cpu(lookup_lock, raw_smp_processor_id()); @@ -254,7 +254,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, input.timer_flag = timer_flag; spin_lock_irqsave(lock, flags); - if (!active) + if (!timer_stats_active) goto out_unlock; entry = tstat_lookup(&input, comm); @@ -290,7 +290,7 @@ static int tstats_show(struct seq_file *m, void *v) /* * If still active then calculate up to now: */ - if (active) + if (timer_stats_active) time_stop = ktime_get(); time = ktime_sub(time_stop, time_start); @@ -368,18 +368,18 @@ static ssize_t tstats_write(struct file *file, const char __user *buf, mutex_lock(&show_mutex); switch (ctl[0]) { case '0': - if (active) { - active = 0; + if (timer_stats_active) { + timer_stats_active = 0; time_stop = ktime_get(); sync_access(); } break; case '1': - if (!active) { + if (!timer_stats_active) { reset_entries(); time_start = ktime_get(); smp_mb(); - active = 1; + timer_stats_active = 1; } break; default: diff --git a/kernel/timer.c b/kernel/timer.c index 54d3912f8cadd..0b36b9e5cc8b4 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -380,6 +380,8 @@ static void timer_stats_account_timer(struct timer_list *timer) { unsigned int flag = 0; + if (likely(!timer->start_site)) + return; if (unlikely(tbase_get_deferrable(timer->base))) flag |= TIMER_STATS_FLAG_DEFERRABLE; -- GitLab From 2a13877c5ef3207a2a5c56250742e60808677f90 Mon Sep 17 00:00:00 2001 From: Jeff Garzik <jeff@garzik.org> Date: Fri, 10 Apr 2009 07:50:45 -0400 Subject: [PATCH 0126/1002] osdblk: a Linux block device for OSD objects Submitted driver exports a block device of the form /dev/osdblkX, where X is a decimal number. It does that by mounting a stacking block device on top of an osd object. For example, if you create a 2G object on an OSD device, you can then use this module to present that 2G object as a Linux block device. See inside patch for exact documentation. [Sitting at linux-next helped fix proper Kconfig dependency for this driver, thanks to Randy Dunlap] Signed-off-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/block/Kconfig | 16 + drivers/block/Makefile | 1 + drivers/block/osdblk.c | 694 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 711 insertions(+) create mode 100644 drivers/block/osdblk.c diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index bb72ada9f0745..1d886e079c588 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -298,6 +298,22 @@ config BLK_DEV_NBD If unsure, say N. +config BLK_DEV_OSD + tristate "OSD object-as-blkdev support" + depends on SCSI_OSD_ULD + ---help--- + Saying Y or M here will allow the exporting of a single SCSI + OSD (object-based storage) object as a Linux block device. + + For example, if you create a 2G object on an OSD device, + you can then use this module to present that 2G object as + a Linux block device. + + To compile this driver as a module, choose M here: the + module will be called osdblk. + + If unsure, say N. + config BLK_DEV_SX8 tristate "Promise SATA SX8 support" depends on PCI diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 7755a5e2a85e3..cdaa3f8fddf03 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o obj-$(CONFIG_MG_DISK) += mg_disk.o obj-$(CONFIG_SUNVDC) += sunvdc.o +obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c new file mode 100644 index 0000000000000..3565d0dd123fa --- /dev/null +++ b/drivers/block/osdblk.c @@ -0,0 +1,694 @@ + +/* + osdblk.c -- Export a single SCSI OSD object as a Linux block device + + + Copyright 2009 Red Hat, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + + Instructions for use + -------------------- + + 1) Map a Linux block device to an existing OSD object. + + In this example, we will use partition id 1234, object id 5678, + OSD device /dev/osd1. + + $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add + + + 2) List all active blkdev<->object mappings. + + In this example, we have performed step #1 twice, creating two blkdevs, + mapped to two separate OSD objects. + + $ cat /sys/class/osdblk/list + 0 174 1234 5678 /dev/osd1 + 1 179 1994 897123 /dev/osd0 + + The columns, in order, are: + - blkdev unique id + - blkdev assigned major + - OSD object partition id + - OSD object id + - OSD device + + + 3) Remove an active blkdev<->object mapping. + + In this example, we remove the mapping with blkdev unique id 1. + + $ echo 1 > /sys/class/osdblk/remove + + + NOTE: The actual creation and deletion of OSD objects is outside the scope + of this driver. + + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <scsi/osd_initiator.h> +#include <scsi/osd_attributes.h> +#include <scsi/osd_sec.h> + +#define DRV_NAME "osdblk" +#define PFX DRV_NAME ": " + +/* #define _OSDBLK_DEBUG */ +#ifdef _OSDBLK_DEBUG +#define OSDBLK_DEBUG(fmt, a...) \ + printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a) +#else +#define OSDBLK_DEBUG(fmt, a...) \ + do { if (0) printk(fmt, ##a); } while (0) +#endif + +MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>"); +MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko"); +MODULE_LICENSE("GPL"); + +struct osdblk_device; + +enum { + OSDBLK_MINORS_PER_MAJOR = 256, /* max minors per blkdev */ + OSDBLK_MAX_REQ = 32, /* max parallel requests */ + OSDBLK_OP_TIMEOUT = 4 * 60, /* sync OSD req timeout */ +}; + +struct osdblk_request { + struct request *rq; /* blk layer request */ + struct bio *bio; /* cloned bio */ + struct osdblk_device *osdev; /* associated blkdev */ +}; + +struct osdblk_device { + int id; /* blkdev unique id */ + + int major; /* blkdev assigned major */ + struct gendisk *disk; /* blkdev's gendisk and rq */ + struct request_queue *q; + + struct osd_dev *osd; /* associated OSD */ + + char name[32]; /* blkdev name, e.g. osdblk34 */ + + spinlock_t lock; /* queue lock */ + + struct osd_obj_id obj; /* OSD partition, obj id */ + uint8_t obj_cred[OSD_CAP_LEN]; /* OSD cred */ + + struct osdblk_request req[OSDBLK_MAX_REQ]; /* request table */ + + struct list_head node; + + char osd_path[0]; /* OSD device path */ +}; + +static struct class *class_osdblk; /* /sys/class/osdblk */ +static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ +static LIST_HEAD(osdblkdev_list); + +static struct block_device_operations osdblk_bd_ops = { + .owner = THIS_MODULE, +}; + +static const struct osd_attr g_attr_logical_length = ATTR_DEF( + OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); + +static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN], + const struct osd_obj_id *obj) +{ + osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); +} + +/* copied from exofs; move to libosd? */ +/* + * Perform a synchronous OSD operation. copied from exofs; move to libosd? + */ +static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential) +{ + int ret; + + or->timeout = timeout; + ret = osd_finalize_request(or, 0, credential, NULL); + if (ret) + return ret; + + ret = osd_execute_request(or); + + /* osd_req_decode_sense(or, ret); */ + return ret; +} + +/* + * Perform an asynchronous OSD operation. copied from exofs; move to libosd? + */ +static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done, + void *caller_context, u8 *cred) +{ + int ret; + + ret = osd_finalize_request(or, 0, cred, NULL); + if (ret) + return ret; + + ret = osd_execute_request_async(or, async_done, caller_context); + + return ret; +} + +/* copied from exofs; move to libosd? */ +static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) +{ + struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ + void *iter = NULL; + int nelem; + + do { + nelem = 1; + osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); + if ((cur_attr.attr_page == attr->attr_page) && + (cur_attr.attr_id == attr->attr_id)) { + attr->len = cur_attr.len; + attr->val_ptr = cur_attr.val_ptr; + return 0; + } + } while (iter); + + return -EIO; +} + +static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out) +{ + struct osd_request *or; + struct osd_attr attr; + int ret; + + /* start request */ + or = osd_start_request(osdev->osd, GFP_KERNEL); + if (!or) + return -ENOMEM; + + /* create a get-attributes(length) request */ + osd_req_get_attributes(or, &osdev->obj); + + osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); + + /* execute op synchronously */ + ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred); + if (ret) + goto out; + + /* extract length from returned attribute info */ + attr = g_attr_logical_length; + ret = extract_attr_from_req(or, &attr); + if (ret) + goto out; + + *size_out = get_unaligned_be64(attr.val_ptr); + +out: + osd_end_request(or); + return ret; + +} + +static void osdblk_osd_complete(struct osd_request *or, void *private) +{ + struct osdblk_request *orq = private; + struct osd_sense_info osi; + int ret = osd_req_decode_sense(or, &osi); + + if (ret) { + ret = -EIO; + OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret); + } + + /* complete OSD request */ + osd_end_request(or); + + /* complete request passed to osdblk by block layer */ + __blk_end_request_all(orq->rq, ret); +} + +static void bio_chain_put(struct bio *chain) +{ + struct bio *tmp; + + while (chain) { + tmp = chain; + chain = chain->bi_next; + + bio_put(tmp); + } +} + +static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask) +{ + struct bio *tmp, *new_chain = NULL, *tail = NULL; + + while (old_chain) { + tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); + if (!tmp) + goto err_out; + + __bio_clone(tmp, old_chain); + tmp->bi_bdev = NULL; + gfpmask &= ~__GFP_WAIT; + tmp->bi_next = NULL; + + if (!new_chain) + new_chain = tail = tmp; + else { + tail->bi_next = tmp; + tail = tmp; + } + + old_chain = old_chain->bi_next; + } + + return new_chain; + +err_out: + OSDBLK_DEBUG("bio_chain_clone with err\n"); + bio_chain_put(new_chain); + return NULL; +} + +static void osdblk_rq_fn(struct request_queue *q) +{ + struct osdblk_device *osdev = q->queuedata; + + while (1) { + struct request *rq; + struct osdblk_request *orq; + struct osd_request *or; + struct bio *bio; + bool do_write, do_flush; + + /* peek at request from block layer */ + rq = blk_fetch_request(q); + if (!rq) + break; + + /* filter out block requests we don't understand */ + if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { + blk_end_request_all(rq, 0); + continue; + } + + /* deduce our operation (read, write, flush) */ + /* I wish the block layer simplified cmd_type/cmd_flags/cmd[] + * into a clearly defined set of RPC commands: + * read, write, flush, scsi command, power mgmt req, + * driver-specific, etc. + */ + + do_flush = (rq->special == (void *) 0xdeadbeefUL); + do_write = (rq_data_dir(rq) == WRITE); + + if (!do_flush) { /* osd_flush does not use a bio */ + /* a bio clone to be passed down to OSD request */ + bio = bio_chain_clone(rq->bio, GFP_ATOMIC); + if (!bio) + break; + } else + bio = NULL; + + /* alloc internal OSD request, for OSD command execution */ + or = osd_start_request(osdev->osd, GFP_ATOMIC); + if (!or) { + bio_chain_put(bio); + OSDBLK_DEBUG("osd_start_request with err\n"); + break; + } + + orq = &osdev->req[rq->tag]; + orq->rq = rq; + orq->bio = bio; + orq->osdev = osdev; + + /* init OSD command: flush, write or read */ + if (do_flush) + osd_req_flush_object(or, &osdev->obj, + OSD_CDB_FLUSH_ALL, 0, 0); + else if (do_write) + osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, + bio, blk_rq_bytes(rq)); + else + osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, + bio, blk_rq_bytes(rq)); + + OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n", + do_flush ? "flush" : do_write ? + "write" : "read", blk_rq_bytes(rq), + blk_rq_pos(rq) * 512ULL); + + /* begin OSD command execution */ + if (osd_async_op(or, osdblk_osd_complete, orq, + osdev->obj_cred)) { + osd_end_request(or); + blk_requeue_request(q, rq); + bio_chain_put(bio); + OSDBLK_DEBUG("osd_execute_request_async with err\n"); + break; + } + + /* remove the special 'flush' marker, now that the command + * is executing + */ + rq->special = NULL; + } +} + +static void osdblk_prepare_flush(struct request_queue *q, struct request *rq) +{ + /* add driver-specific marker, to indicate that this request + * is a flush command + */ + rq->special = (void *) 0xdeadbeefUL; +} + +static void osdblk_free_disk(struct osdblk_device *osdev) +{ + struct gendisk *disk = osdev->disk; + + if (!disk) + return; + + if (disk->flags & GENHD_FL_UP) + del_gendisk(disk); + if (disk->queue) + blk_cleanup_queue(disk->queue); + put_disk(disk); +} + +static int osdblk_init_disk(struct osdblk_device *osdev) +{ + struct gendisk *disk; + struct request_queue *q; + int rc; + u64 obj_size = 0; + + /* contact OSD, request size info about the object being mapped */ + rc = osdblk_get_obj_size(osdev, &obj_size); + if (rc) + return rc; + + /* create gendisk info */ + disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR); + if (!disk) + return -ENOMEM; + + sprintf(disk->disk_name, DRV_NAME "%d", osdev->id); + disk->major = osdev->major; + disk->first_minor = 0; + disk->fops = &osdblk_bd_ops; + disk->private_data = osdev; + + /* init rq */ + q = blk_init_queue(osdblk_rq_fn, &osdev->lock); + if (!q) { + put_disk(disk); + return -ENOMEM; + } + + /* switch queue to TCQ mode; allocate tag map */ + rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL); + if (rc) { + blk_cleanup_queue(q); + put_disk(disk); + return rc; + } + + blk_queue_prep_rq(q, blk_queue_start_tag); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); + + disk->queue = q; + + q->queuedata = osdev; + + osdev->disk = disk; + osdev->q = q; + + /* finally, announce the disk to the world */ + set_capacity(disk, obj_size / 512ULL); + add_disk(disk); + + printk(KERN_INFO "%s: Added of size 0x%llx\n", + disk->disk_name, (unsigned long long)obj_size); + + return 0; +} + +/******************************************************************** + * /sys/class/osdblk/ + * add map OSD object to blkdev + * remove unmap OSD object + * list show mappings + *******************************************************************/ + +static void class_osdblk_release(struct class *cls) +{ + kfree(cls); +} + +static ssize_t class_osdblk_list(struct class *c, char *data) +{ + int n = 0; + struct list_head *tmp; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + list_for_each(tmp, &osdblkdev_list) { + struct osdblk_device *osdev; + + osdev = list_entry(tmp, struct osdblk_device, node); + + n += sprintf(data+n, "%d %d %llu %llu %s\n", + osdev->id, + osdev->major, + osdev->obj.partition, + osdev->obj.id, + osdev->osd_path); + } + + mutex_unlock(&ctl_mutex); + return n; +} + +static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) +{ + struct osdblk_device *osdev; + ssize_t rc; + int irc, new_id = 0; + struct list_head *tmp; + + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + /* new osdblk_device object */ + osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL); + if (!osdev) { + rc = -ENOMEM; + goto err_out_mod; + } + + /* static osdblk_device initialization */ + spin_lock_init(&osdev->lock); + INIT_LIST_HEAD(&osdev->node); + + /* generate unique id: find highest unique id, add one */ + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + list_for_each(tmp, &osdblkdev_list) { + struct osdblk_device *osdev; + + osdev = list_entry(tmp, struct osdblk_device, node); + if (osdev->id > new_id) + new_id = osdev->id + 1; + } + + osdev->id = new_id; + + /* add to global list */ + list_add_tail(&osdev->node, &osdblkdev_list); + + mutex_unlock(&ctl_mutex); + + /* parse add command */ + if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id, + osdev->osd_path) != 3) { + rc = -EINVAL; + goto err_out_slot; + } + + /* initialize rest of new object */ + sprintf(osdev->name, DRV_NAME "%d", osdev->id); + + /* contact requested OSD */ + osdev->osd = osduld_path_lookup(osdev->osd_path); + if (IS_ERR(osdev->osd)) { + rc = PTR_ERR(osdev->osd); + goto err_out_slot; + } + + /* build OSD credential */ + osdblk_make_credential(osdev->obj_cred, &osdev->obj); + + /* register our block device */ + irc = register_blkdev(0, osdev->name); + if (irc < 0) { + rc = irc; + goto err_out_osd; + } + + osdev->major = irc; + + /* set up and announce blkdev mapping */ + rc = osdblk_init_disk(osdev); + if (rc) + goto err_out_blkdev; + + return count; + +err_out_blkdev: + unregister_blkdev(osdev->major, osdev->name); +err_out_osd: + osduld_put_device(osdev->osd); +err_out_slot: + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + list_del_init(&osdev->node); + mutex_unlock(&ctl_mutex); + + kfree(osdev); +err_out_mod: + OSDBLK_DEBUG("Error adding device %s\n", buf); + module_put(THIS_MODULE); + return rc; +} + +static ssize_t class_osdblk_remove(struct class *c, const char *buf, + size_t count) +{ + struct osdblk_device *osdev = NULL; + int target_id, rc; + unsigned long ul; + struct list_head *tmp; + + rc = strict_strtoul(buf, 10, &ul); + if (rc) + return rc; + + /* convert to int; abort if we lost anything in the conversion */ + target_id = (int) ul; + if (target_id != ul) + return -EINVAL; + + /* remove object from list immediately */ + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + list_for_each(tmp, &osdblkdev_list) { + osdev = list_entry(tmp, struct osdblk_device, node); + if (osdev->id == target_id) { + list_del_init(&osdev->node); + break; + } + osdev = NULL; + } + + mutex_unlock(&ctl_mutex); + + if (!osdev) + return -ENOENT; + + /* clean up and free blkdev and associated OSD connection */ + osdblk_free_disk(osdev); + unregister_blkdev(osdev->major, osdev->name); + osduld_put_device(osdev->osd); + kfree(osdev); + + /* release module ref */ + module_put(THIS_MODULE); + + return count; +} + +static struct class_attribute class_osdblk_attrs[] = { + __ATTR(add, 0200, NULL, class_osdblk_add), + __ATTR(remove, 0200, NULL, class_osdblk_remove), + __ATTR(list, 0444, class_osdblk_list, NULL), + __ATTR_NULL +}; + +static int osdblk_sysfs_init(void) +{ + int ret = 0; + + /* + * create control files in sysfs + * /sys/class/osdblk/... + */ + class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL); + if (!class_osdblk) + return -ENOMEM; + + class_osdblk->name = DRV_NAME; + class_osdblk->owner = THIS_MODULE; + class_osdblk->class_release = class_osdblk_release; + class_osdblk->class_attrs = class_osdblk_attrs; + + ret = class_register(class_osdblk); + if (ret) { + kfree(class_osdblk); + class_osdblk = NULL; + printk(PFX "failed to create class osdblk\n"); + return ret; + } + + return 0; +} + +static void osdblk_sysfs_cleanup(void) +{ + if (class_osdblk) + class_destroy(class_osdblk); + class_osdblk = NULL; +} + +static int __init osdblk_init(void) +{ + int rc; + + rc = osdblk_sysfs_init(); + if (rc) + return rc; + + return 0; +} + +static void __exit osdblk_exit(void) +{ + osdblk_sysfs_cleanup(); +} + +module_init(osdblk_init); +module_exit(osdblk_exit); + -- GitLab From bc47df0fa705887242c26c7b040e7cf0170ab1f1 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh <bharrosh@panasas.com> Date: Wed, 20 May 2009 18:50:34 +0300 Subject: [PATCH 0127/1002] osdblk: Adjust queue limits to lower device's limits call blk_queue_stack_limits() to copy queue limits from the underline osd scsi_device. This is absolutely needed because osdblk cannot sleep when allocating a lower-request and therefore cannot be bouncing. TODO: Dynamic changes of limits to the lower device queue will not reflect in the upper driver Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/block/osdblk.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index 3565d0dd123fa..13c1aee6aa3f4 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -66,6 +66,7 @@ #include <scsi/osd_initiator.h> #include <scsi/osd_attributes.h> #include <scsi/osd_sec.h> +#include <scsi/scsi_device.h> #define DRV_NAME "osdblk" #define PFX DRV_NAME ": " @@ -437,6 +438,12 @@ static int osdblk_init_disk(struct osdblk_device *osdev) return rc; } + /* Set our limits to the lower device limits, because osdblk cannot + * sleep when allocating a lower-request and therefore cannot be + * bouncing. + */ + blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); + blk_queue_prep_rq(q, blk_queue_start_tag); blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); -- GitLab From d7e2f36d9a92284754ed5254562766cb3d61c7ca Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Wed, 24 Jun 2009 02:36:17 -0700 Subject: [PATCH 0128/1002] ide cs5520: Initialize second port's interrupt number. In 86ccf37c6acd74cf7e4b7751ee045de19943c5a0 the driver was modified to deal with the removal of the pciirq argument to ide_pci_setup_ports(). But in the conversion only the first port's IRQ gets setup. Inspired by a patch by Bartlomiej Zolnierkiewicz., and with help from Alan Cox. Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/cs5520.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index bd066bb9d6110..09f98ed0731fa 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c @@ -135,6 +135,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); hw[0].irq = 14; + hw[1].irq = 15; return ide_host_add(d, hws, 2, NULL); } -- GitLab From 9d612beff5089b89a295a2331883a8ce3fff08c1 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Wed, 24 Jun 2009 17:33:15 +0800 Subject: [PATCH 0129/1002] tracing: Fix trace_buf_size boot option We should be able to specify [KMG] when setting trace_buf_size boot option, as documented in kernel-parameters.txt Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A41F2DB.4020102@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- Documentation/kernel-parameters.txt | 3 ++- kernel/trace/trace.c | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 92e1ab8178a86..d3f41db3ed498 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2475,7 +2475,8 @@ and is between 256 and 4096 characters. It is defined in the file tp720= [HW,PS2] - trace_buf_size=nn[KMG] [ftrace] will set tracing buffer size. + trace_buf_size=nn[KMG] + [FTRACE] will set tracing buffer size. trix= [HW,OSS] MediaTrix AudioTrix Pro Format: diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 3bb31006b5cca..3aa0a0dfdfa81 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -284,13 +284,12 @@ void trace_wake_up(void) static int __init set_buf_size(char *str) { unsigned long buf_size; - int ret; if (!str) return 0; - ret = strict_strtoul(str, 0, &buf_size); + buf_size = memparse(str, &str); /* nr_entries can not be zero */ - if (ret < 0 || buf_size == 0) + if (buf_size == 0) return 0; trace_buf_size = buf_size; return 1; -- GitLab From 16d11a829ed197b719723f81d82e7f1a42f5c681 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 24 Jun 2009 14:07:53 +0200 Subject: [PATCH 0130/1002] ALSA: hda - Simplify AD1986A mixer definitions Split mixer element arrays of AD1986A models to several pieces so that each model can share the same mixer arrays. This removes lots of duplicated data. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_analog.c | 77 ++++++++++-------------------------- 1 file changed, 21 insertions(+), 56 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 84cc49ca91487..592423c878f2e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -669,39 +669,13 @@ static struct hda_input_mux ad1986a_automic_capture_source = { }, }; -static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { +static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External Amplifier", - .info = ad198x_eapd_info, - .get = ad198x_eapd_get, - .put = ad198x_eapd_put, - .private_value = 0x1b | (1 << 8), /* port-D, inversed */ - }, { } /* end */ }; -static struct snd_kcontrol_new ad1986a_samsung_mixers[] = { - HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), - HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), +static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), @@ -727,6 +701,12 @@ static struct snd_kcontrol_new ad1986a_samsung_mixers[] = { { } /* end */ }; +static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { + HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), + { } /* end */ +}; + /* re-connect the mic boost input according to the jack sensing */ static void ad1986a_automic(struct hda_codec *codec) { @@ -816,7 +796,7 @@ static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, return change; } -static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { +static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -826,33 +806,10 @@ static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { .put = ad1986a_hp_master_sw_put, .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), }, - HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External Amplifier", - .info = ad198x_eapd_info, - .get = ad198x_eapd_get, - .put = ad198x_eapd_put, - .private_value = 0x1b | (1 << 8), /* port-D, inversed */ - }, { } /* end */ }; + /* * initialization verbs */ @@ -1111,7 +1068,10 @@ static int patch_ad1986a(struct hda_codec *codec) spec->multiout.dac_nids = ad1986a_laptop_dac_nids; break; case AD1986A_LAPTOP_EAPD: - spec->mixers[0] = ad1986a_laptop_eapd_mixers; + spec->num_mixers = 3; + spec->mixers[0] = ad1986a_laptop_master_mixers; + spec->mixers[1] = ad1986a_laptop_eapd_mixers; + spec->mixers[2] = ad1986a_laptop_intmic_mixers; spec->num_init_verbs = 2; spec->init_verbs[1] = ad1986a_eapd_init_verbs; spec->multiout.max_channels = 2; @@ -1122,7 +1082,9 @@ static int patch_ad1986a(struct hda_codec *codec) spec->input_mux = &ad1986a_laptop_eapd_capture_source; break; case AD1986A_SAMSUNG: - spec->mixers[0] = ad1986a_samsung_mixers; + spec->num_mixers = 2; + spec->mixers[0] = ad1986a_laptop_master_mixers; + spec->mixers[1] = ad1986a_laptop_eapd_mixers; spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; spec->init_verbs[2] = ad1986a_automic_verbs; @@ -1136,7 +1098,10 @@ static int patch_ad1986a(struct hda_codec *codec) codec->patch_ops.init = ad1986a_automic_init; break; case AD1986A_LAPTOP_AUTOMUTE: - spec->mixers[0] = ad1986a_laptop_automute_mixers; + spec->num_mixers = 3; + spec->mixers[0] = ad1986a_automute_master_mixers; + spec->mixers[1] = ad1986a_laptop_eapd_mixers; + spec->mixers[2] = ad1986a_laptop_intmic_mixers; spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; spec->init_verbs[2] = ad1986a_hp_init_verbs; -- GitLab From 6f4b67b8ff707147e14ee71045ab25aa286520f2 Mon Sep 17 00:00:00 2001 From: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp> Date: Sun, 21 Jun 2009 10:56:22 +0000 Subject: [PATCH 0131/1002] clocksource: sh_tmu: Make undefined TCOR behaviour less undefined. Avoid undocumented vague TMU behavior when zero value is set to TCOR. This primarily fixes up issues encountered under qemu with a zero-length period, while the hardware itself is fairly ambivalent one way or the other. Signed-off-by: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp> Acked-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/clocksource/sh_tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 9ffb05f4095d7..93c2322feab79 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -161,7 +161,7 @@ static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, if (periodic) sh_tmu_write(p, TCOR, delta); else - sh_tmu_write(p, TCOR, 0); + sh_tmu_write(p, TCOR, 0xffffffff); sh_tmu_write(p, TCNT, delta); -- GitLab From 03c405ad314d3c4e049b8d04500e54e833d16747 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 24 Jun 2009 14:10:15 +0200 Subject: [PATCH 0132/1002] ALSA: hda - Generalize the pin-detect quirk for Lenovo N100 Add a new flag to ad_spec struct so that the same hack can be used for any other models (if any). This also allows other models to reuse the auto-mute functions. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_analog.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 592423c878f2e..8c2b23f54f952 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -72,6 +72,7 @@ struct ad198x_spec { hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; unsigned int jack_present :1; + unsigned int inv_jack_detect:1; #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_loopback_check loopback; @@ -756,8 +757,9 @@ static void ad1986a_hp_automute(struct hda_codec *codec) unsigned int present; present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); - /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */ - spec->jack_present = !(present & 0x80000000); + spec->jack_present = !!(present & 0x80000000); + if (spec->inv_jack_detect) + spec->jack_present = !spec->jack_present; ad1986a_update_hp(codec); } @@ -1113,6 +1115,10 @@ static int patch_ad1986a(struct hda_codec *codec) spec->input_mux = &ad1986a_laptop_eapd_capture_source; codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; codec->patch_ops.init = ad1986a_hp_init; + /* Lenovo N100 seems to report the reversed bit + * for HP jack-sensing + */ + spec->inv_jack_detect = 1; break; case AD1986A_ULTRA: spec->mixers[0] = ad1986a_laptop_eapd_mixers; -- GitLab From c912e7a58054304575fe88574c776be7e684098e Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 24 Jun 2009 14:14:34 +0200 Subject: [PATCH 0133/1002] ALSA: hda - Fix support for Samsung P50 with AD1986A codec Samsung P50 requires the HP auto-muting unlike other Samsung models. Added a new model=samsung-p50 to support this. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- Documentation/sound/alsa/HD-Audio-Models.txt | 1 + sound/pci/hda/patch_analog.c | 41 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 0d8d23581c44e..939a3dd581481 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -240,6 +240,7 @@ AD1986A laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100) ultra 2-channel with EAPD (Samsung Ultra tablet PC) samsung 2-channel with EAPD (Samsung R65) + samsung-p50 2-channel with HP-automute (Samsung P50) AD1988/AD1988B/AD1989A/AD1989B ============================== diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 8c2b23f54f952..1988582d1ab8f 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -940,6 +940,27 @@ static struct hda_verb ad1986a_hp_init_verbs[] = { {} }; +static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case AD1986A_HP_EVENT: + ad1986a_hp_automute(codec); + break; + case AD1986A_MIC_EVENT: + ad1986a_automic(codec); + break; + } +} + +static int ad1986a_samsung_p50_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1986a_hp_automute(codec); + ad1986a_automic(codec); + return 0; +} + /* models */ enum { @@ -950,6 +971,7 @@ enum { AD1986A_LAPTOP_AUTOMUTE, AD1986A_ULTRA, AD1986A_SAMSUNG, + AD1986A_SAMSUNG_P50, AD1986A_MODELS }; @@ -961,6 +983,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = { [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", [AD1986A_ULTRA] = "ultra", [AD1986A_SAMSUNG] = "samsung", + [AD1986A_SAMSUNG_P50] = "samsung-p50", }; static struct snd_pci_quirk ad1986a_cfg_tbl[] = { @@ -983,6 +1006,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), + SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), @@ -1099,6 +1123,23 @@ static int patch_ad1986a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; codec->patch_ops.init = ad1986a_automic_init; break; + case AD1986A_SAMSUNG_P50: + spec->num_mixers = 2; + spec->mixers[0] = ad1986a_automute_master_mixers; + spec->mixers[1] = ad1986a_laptop_eapd_mixers; + spec->num_init_verbs = 4; + spec->init_verbs[1] = ad1986a_eapd_init_verbs; + spec->init_verbs[2] = ad1986a_automic_verbs; + spec->init_verbs[3] = ad1986a_hp_init_verbs; + spec->multiout.max_channels = 2; + spec->multiout.num_dacs = 1; + spec->multiout.dac_nids = ad1986a_laptop_dac_nids; + if (!is_jack_available(codec, 0x25)) + spec->multiout.dig_out_nid = 0; + spec->input_mux = &ad1986a_automic_capture_source; + codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event; + codec->patch_ops.init = ad1986a_samsung_p50_init; + break; case AD1986A_LAPTOP_AUTOMUTE: spec->num_mixers = 3; spec->mixers[0] = ad1986a_automute_master_mixers; -- GitLab From 3d63259583278262d9153316094e315f73ebfcb5 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 24 Jun 2009 18:19:34 +0530 Subject: [PATCH 0134/1002] perf stat: Remove dead code Remove dead code and do some code alignment. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245847774.2681.2.camel@ht.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 44 ++++++++++++--------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 5e04fcc8d0776..8420ec589506f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -59,42 +59,27 @@ static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { }; +#define MAX_RUN 100 + static int system_wide = 0; -static int inherit = 1; static int verbose = 0; - -static int fd[MAX_NR_CPUS][MAX_COUNTERS]; - -static int target_pid = -1; static int nr_cpus = 0; -static unsigned int page_size; +static int run_idx = 0; +static int run_count = 1; +static int inherit = 1; static int scale = 1; +static int target_pid = -1; -static const unsigned int default_count[] = { - 1000000, - 1000000, - 10000, - 10000, - 1000000, - 10000, -}; - -#define MAX_RUN 100 - -static int run_count = 1; -static int run_idx = 0; - -static u64 event_res[MAX_RUN][MAX_COUNTERS][3]; -static u64 event_scaled[MAX_RUN][MAX_COUNTERS]; - -//static u64 event_hist[MAX_RUN][MAX_COUNTERS][3]; - +static int fd[MAX_NR_CPUS][MAX_COUNTERS]; static u64 runtime_nsecs[MAX_RUN]; static u64 walltime_nsecs[MAX_RUN]; static u64 runtime_cycles[MAX_RUN]; +static u64 event_res[MAX_RUN][MAX_COUNTERS][3]; +static u64 event_scaled[MAX_RUN][MAX_COUNTERS]; + static u64 event_res_avg[MAX_COUNTERS][3]; static u64 event_res_noise[MAX_COUNTERS][3]; @@ -109,7 +94,6 @@ static u64 walltime_nsecs_noise; static u64 runtime_cycles_avg; static u64 runtime_cycles_noise; - #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" @@ -470,9 +454,9 @@ static const struct option options[] = { OPT_INTEGER('p', "pid", &target_pid, "stat events on existing pid"), OPT_BOOLEAN('a', "all-cpus", &system_wide, - "system-wide collection from all CPUs"), + "system-wide collection from all CPUs"), OPT_BOOLEAN('S', "scale", &scale, - "scale/normalize counters"), + "scale/normalize counters"), OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_INTEGER('r', "repeat", &run_count, @@ -484,8 +468,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix) { int status; - page_size = sysconf(_SC_PAGE_SIZE); - memcpy(attrs, default_attrs, sizeof(attrs)); argc = parse_options(argc, argv, options, stat_usage, 0); @@ -515,7 +497,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix) status = 0; for (run_idx = 0; run_idx < run_count; run_idx++) { if (run_count != 1 && verbose) - fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1); + fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); status = run_perf_stat(argc, argv); } -- GitLab From f6faac71d502be1c29c81b2f45657662c3b84470 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Date: Tue, 23 Jun 2009 17:24:40 -0700 Subject: [PATCH 0135/1002] rcu: Mark Hierarchical RCU no longer experimental Removes the warnings about Hierarchical RCU being experimental, given that it has gone through almost six months of being the default RCU in mainline for the x86 with very little trouble. This makes hierarchical-RCU bootup look less scary. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: akpm@linux-foundation.org Cc: niv@us.ibm.com Cc: dvhltc@us.ibm.com Cc: dipankar@in.ibm.com Cc: dhowells@redhat.com Cc: lethal@linux-sh.org Cc: kernel@wantstofly.org Cc: cl@linux-foundation.org Cc: schamp@sgi.com Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/rcutree.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 0dccfbba6d267..7717b95c20278 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1533,7 +1533,7 @@ void __init __rcu_init(void) int j; struct rcu_node *rnp; - printk(KERN_WARNING "Experimental hierarchical RCU implementation.\n"); + printk(KERN_INFO "Hierarchical RCU implementation.\n"); #ifdef CONFIG_RCU_CPU_STALL_DETECTOR printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n"); #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ @@ -1546,7 +1546,6 @@ void __init __rcu_init(void) rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i); /* Register notifier for non-boot CPUs */ register_cpu_notifier(&rcu_nb); - printk(KERN_WARNING "Experimental hierarchical RCU init done.\n"); } module_param(blimit, int, 0); -- GitLab From d94d4adb7dd05b4e25f3c317a1b932ec74272a12 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Wed, 24 Jun 2009 22:35:30 +0900 Subject: [PATCH 0136/1002] sh: make set_perf_counter_pending() static inline. Fixes up a recently introduced build error. Reported-by: Kyle McMartin <kyle@mcmartin.ca> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/include/asm/perf_counter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/include/asm/perf_counter.h b/arch/sh/include/asm/perf_counter.h index a8153c2aa6faf..61c2b40c802cf 100644 --- a/arch/sh/include/asm/perf_counter.h +++ b/arch/sh/include/asm/perf_counter.h @@ -2,6 +2,6 @@ #define __ASM_SH_PERF_COUNTER_H /* SH only supports software counters through this interface. */ -#define set_perf_counter_pending() do { } while (0) +static inline void set_perf_counter_pending(void) {} #endif /* __ASM_SH_PERF_COUNTER_H */ -- GitLab From 17659c60629618c0aa67eb3cb6a77d2c52486d2e Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 24 Jun 2009 15:35:15 +0100 Subject: [PATCH 0137/1002] mtd: maps: Remove BUS_ID_SIZE from integrator_flash Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Tested-by: Catalin Marinas <catalin.marinas@arm.com> --- drivers/mtd/maps/integrator-flash.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index b08a798ee254b..2aac41bde8b31 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -42,10 +42,8 @@ #include <mach/hardware.h> #include <asm/system.h> -#define SUBDEV_NAME_SIZE (BUS_ID_SIZE + 2) - struct armflash_subdev_info { - char name[SUBDEV_NAME_SIZE]; + char *name; struct mtd_info *mtd; struct map_info map; struct flash_platform_data *plat; @@ -134,6 +132,8 @@ static void armflash_subdev_remove(struct armflash_subdev_info *subdev) map_destroy(subdev->mtd); if (subdev->map.virt) iounmap(subdev->map.virt); + kfree(subdev->name); + subdev->name = NULL; release_mem_region(subdev->map.phys, subdev->map.size); } @@ -177,16 +177,22 @@ static int armflash_probe(struct platform_device *dev) if (nr == 1) /* No MTD concatenation, just use the default name */ - snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s", - dev_name(&dev->dev)); + subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL); else - snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d", - dev_name(&dev->dev), i); + subdev->name = kasprintf(GFP_KERNEL, "%s-%d", + dev_name(&dev->dev), i); + if (!subdev->name) { + err = -ENOMEM; + break; + } subdev->plat = plat; err = armflash_subdev_probe(subdev, res); - if (err) + if (err) { + kfree(subdev->name); + subdev->name = NULL; break; + } } info->nr_subdev = i; -- GitLab From 9c26f52b900f7207135bafc8789e1a4f5d43e096 Mon Sep 17 00:00:00 2001 From: Cliff Wickman <cpw@sgi.com> Date: Wed, 24 Jun 2009 09:41:59 -0500 Subject: [PATCH 0138/1002] x86: Fix uv bau sending buffer initialization The initialization of the UV Broadcast Assist Unit's sending buffers was making an invalid assumption about the initialization of an MMR that defines its address. The BIOS will not be providing that MMR. So uv_activation_descriptor_init() should unconditionally set it. Tested on UV simulator. Signed-off-by: Cliff Wickman <cpw@sgi.com> Cc: <stable@kernel.org> # for v2.6.30.x LKML-Reference: <E1MJTfj-0005i1-W8@eag09.americas.sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/tlb_uv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 124d40c575df3..8ccabb8a2f6a6 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -711,7 +711,6 @@ uv_activation_descriptor_init(int node, int pnode) unsigned long pa; unsigned long m; unsigned long n; - unsigned long mmr_image; struct bau_desc *adp; struct bau_desc *ad2; @@ -727,12 +726,8 @@ uv_activation_descriptor_init(int node, int pnode) n = pa >> uv_nshift; m = pa & uv_mmask; - mmr_image = uv_read_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE); - if (mmr_image) { - uv_write_global_mmr64(pnode, (unsigned long) - UVH_LB_BAU_SB_DESCRIPTOR_BASE, - (n << UV_DESC_BASE_PNODE_SHIFT | m)); - } + uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, + (n << UV_DESC_BASE_PNODE_SHIFT | m)); /* * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each -- GitLab From 7433ab770327b471399f7b5baacad78e160b5393 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Thu, 25 Jun 2009 02:30:10 +0900 Subject: [PATCH 0139/1002] sh: Hook up page fault events for software perf counters. This adds page fault instrumentation for the software performance counters. Follows the x86 and powerpc changes. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/mm/fault_32.c | 61 +++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index cc8ddbdf3d7a7..71925946f1e16 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -15,12 +15,28 @@ #include <linux/mm.h> #include <linux/hardirq.h> #include <linux/kprobes.h> -#include <linux/marker.h> +#include <linux/perf_counter.h> #include <asm/io_trapped.h> #include <asm/system.h> #include <asm/mmu_context.h> #include <asm/tlbflush.h> +static inline int notify_page_fault(struct pt_regs *regs, int trap) +{ + int ret = 0; + +#ifdef CONFIG_KPROBES + if (!user_mode(regs)) { + preempt_disable(); + if (kprobe_running() && kprobe_fault_handler(regs, trap)) + ret = 1; + preempt_enable(); + } +#endif + + return ret; +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -87,13 +103,16 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, return; } + mm = tsk->mm; + + if (unlikely(notify_page_fault(regs, lookup_exception_vector()))) + return; + /* Only enable interrupts if they were on before the fault */ - if ((regs->sr & SR_IMASK) != SR_IMASK) { - trace_hardirqs_on(); + if ((regs->sr & SR_IMASK) != SR_IMASK) local_irq_enable(); - } - mm = tsk->mm; + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); /* * If we're in an interrupt or have no user @@ -141,10 +160,15 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) + if (fault & VM_FAULT_MAJOR) { tsk->maj_flt++; - else + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, + regs, address); + } else { tsk->min_flt++; + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, + regs, address); + } up_read(&mm->mmap_sem); return; @@ -245,22 +269,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto no_context; } -static inline int notify_page_fault(struct pt_regs *regs, int trap) -{ - int ret = 0; - -#ifdef CONFIG_KPROBES - if (!user_mode(regs)) { - preempt_disable(); - if (kprobe_running() && kprobe_fault_handler(regs, trap)) - ret = 1; - preempt_enable(); - } -#endif - - return ret; -} - /* * Called with interrupts disabled. */ @@ -273,12 +281,7 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, pmd_t *pmd; pte_t *pte; pte_t entry; - int ret = 0; - - if (notify_page_fault(regs, lookup_exception_vector())) - goto out; - - ret = 1; + int ret = 1; /* * We don't take page faults for P1, P2, and parts of P4, these -- GitLab From 163b2f0ba93e9298b3d5fff2337d860c3872ec60 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Thu, 25 Jun 2009 02:49:03 +0900 Subject: [PATCH 0140/1002] sh64: Hook up page fault events for software perf counters. sh64 can use these as well, so tie them up there as well. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/mm/tlbflush_64.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index fcbb6e135cef3..3ce40ea348249 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -3,7 +3,7 @@ * * Copyright (C) 2000, 2001 Paolo Alberelli * Copyright (C) 2003 Richard Curnow (/proc/tlb, bug fixes) - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003 - 2009 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -20,6 +20,7 @@ #include <linux/mman.h> #include <linux/mm.h> #include <linux/smp.h> +#include <linux/perf_counter.h> #include <linux/interrupt.h> #include <asm/system.h> #include <asm/io.h> @@ -115,6 +116,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, /* Not an IO address, so reenable interrupts */ local_irq_enable(); + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); + /* * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -195,10 +198,16 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, goto do_sigbus; BUG(); } - if (fault & VM_FAULT_MAJOR) + + if (fault & VM_FAULT_MAJOR) { tsk->maj_flt++; - else + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, + regs, address); + } else { tsk->min_flt++; + perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, + regs, address); + } /* If we get here, the page fault has been handled. Do the TLB refill now from the newly-setup PTE, to avoid having to fault again right -- GitLab From 1b173f77dd0d5fd4f0ff18034aaa79e30da068b9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Wed, 24 Jun 2009 19:54:29 +0200 Subject: [PATCH 0141/1002] perf_counter tools: Add CREDITS file for Git contributors Much of perf's libraries comes from the Git project. I noticed that the files (in tools/perf/util/*.[ch] and elsewhere) are quite spartan wrt. credits, so lets add a CREDITS file that includes an (incomplete!) list of main contributors. Thanks guys, these libraries are really useful. Special thanks go to Johannes Schindelin and Junio C Hamano for coming up with this list. List-Composed-By: Johannes Schindelin <Johannes.Schindelin@gmx.de> Cc: Junio C Hamano <gitster@pobox.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/CREDITS | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tools/perf/CREDITS diff --git a/tools/perf/CREDITS b/tools/perf/CREDITS new file mode 100644 index 0000000000000..c2ddcb3acbd0a --- /dev/null +++ b/tools/perf/CREDITS @@ -0,0 +1,30 @@ +Most of the infrastructure that 'perf' uses here has been reused +from the Git project, as of version: + + 66996ec: Sync with 1.6.2.4 + +Here is an (incomplete!) list of main contributors to those files +in util/* and elsewhere: + + Alex Riesen + Christian Couder + Dmitry Potapov + Jeff King + Johannes Schindelin + Johannes Sixt + Junio C Hamano + Linus Torvalds + Matthias Kestenholz + Michal Ostrowski + Miklos Vajna + Petr Baudis + Pierre Habouzit + René Scharfe + Samuel Tardieu + Shawn O. Pearce + Steffen Prohaska + Steve Haslam + +Thanks guys! + +The full history of the files can be found in the upstream Git commits. -- GitLab From 268875b9d1dd1bf0b523c59e736da9bc20c8ce1f Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Thu, 25 Jun 2009 00:29:21 +0000 Subject: [PATCH 0142/1002] [CIFS] Do not send tree disconnect if session is already disconnected Noticed this when tree connect timed out (due to Samba server crash) - we try to send a tree disconnect for a tid that does not exist since we don't have a valid tree id yet. This checks that the session is valid before sending the tree disconnect to handle this case. Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/CHANGES | 2 +- fs/cifs/cifssmb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index b486898394288..3a9b7a58a51d0 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -5,7 +5,7 @@ client generated ones by default (mount option "serverino" turned on by default if server supports it). Add forceuid and forcegid mount options (so that when negotiating unix extensions specifying which uid mounted does not immediately force the server's reported -uids to be overridden). +uids to be overridden). Add support for scope moutn parm. Version 1.58 ------------ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b84c61d5bca41..58d65a9a79c3b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) * the tcon is no longer on the list, so no need to take lock before * checking this. */ - if (tcon->need_reconnect) + if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) return 0; rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, -- GitLab From 245acb87729bc76ba65c7476665c01837e0cdccb Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Wed, 24 Jun 2009 03:55:41 -0700 Subject: [PATCH 0143/1002] ipsec: Fix name of CAST algorithm Our CAST algorithm is called cast5, not cast128. Clearly nobody has ever used it :) Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/xfrm/xfrm_algo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index d31ccb487730b..faf54c6bf96be 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(cast128)", - .compat = "cast128", + .name = "cbc(cast5)", + .compat = "cast5", .uinfo = { .encr = { -- GitLab From 6a9b6546164fb380a019f92ca4d76443202fdc4f Mon Sep 17 00:00:00 2001 From: Florian Fainelli <florian@openwrt.org> Date: Wed, 24 Jun 2009 16:32:33 -0700 Subject: [PATCH 0144/1002] cpmac: fix compilation failure introduced with netdev_ops conversion This patch fixes and obvious typo in the netdev_ops initialization: ndo_so_ioctl should be ndo_do_ioctl. Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/cpmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 58afafbd3b9cb..fd5e32cbcb877 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1097,7 +1097,7 @@ static const struct net_device_ops cpmac_netdev_ops = { .ndo_start_xmit = cpmac_start_xmit, .ndo_tx_timeout = cpmac_tx_timeout, .ndo_set_multicast_list = cpmac_set_multicast_list, - .ndo_so_ioctl = cpmac_ioctl, + .ndo_do_ioctl = cpmac_ioctl, .ndo_set_config = cpmac_config, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, -- GitLab From 681bf72e4893a187cf6b6b62c08fc193f81c8c2f Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 11 Jun 2009 10:27:31 -0400 Subject: [PATCH 0145/1002] cifs: have cifs parse scope_id out of IPv6 addresses and use it This patch has CIFS look for a '%' in an IPv6 address. If one is present then it will try to treat that value as a numeric interface index suitable for stuffing into the sin6_scope_id field. This should allow people to mount servers on IPv6 link-local addresses. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: David Holder <david@erion.co.uk> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/connect.c | 6 ++++-- fs/cifs/dns_resolve.c | 4 ++-- fs/cifs/netmisc.c | 32 +++++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c368ad6582367..3fb799ff55c9f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1386,8 +1386,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) server->addr.sockAddr.sin_addr.s_addr)) continue; else if (addr->ss_family == AF_INET6 && - !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, - &addr6->sin6_addr)) + (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, + &addr6->sin6_addr) || + server->addr.sockAddr6.sin6_scope_id != + addr6->sin6_scope_id)) continue; ++server->srv_count; diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 91b5500755bf8..87948147d7ece 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -35,7 +35,7 @@ * 0 - name is not IP */ static int -is_ip(const char *name) +is_ip(char *name) { struct sockaddr_storage ss; @@ -57,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data, ip[datalen] = '\0'; /* make sure this looks like an address */ - if (!is_ip((const char *) ip)) { + if (!is_ip(ip)) { kfree(ip); return -EINVAL; } diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f9a54da97d345..bd6d6895730d8 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -158,25 +158,47 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) /* * Try to convert a string to an IPv4 address and then attempt to convert * it to an IPv6 address if that fails. Set the family field if either - * succeeds. + * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to + * treat the part following it as a numeric sin6_scope_id. * * Returns 0 on failure. */ int cifs_convert_address(char *src, void *dst) { + int rc; + char *pct, *endp; struct sockaddr_in *s4 = (struct sockaddr_in *) dst; struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; + /* IPv4 address */ if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { s4->sin_family = AF_INET; return 1; - } else if (cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr)) { - s6->sin6_family = AF_INET6; - return 1; } - return 0; + /* temporarily terminate string */ + pct = strchr(src, '%'); + if (pct) + *pct = '\0'; + + rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr); + + /* repair temp termination (if any) and make pct point to scopeid */ + if (pct) + *pct++ = '%'; + + if (!rc) + return rc; + + s6->sin6_family = AF_INET6; + if (pct) { + s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); + if (!*pct || *endp) + return 0; + } + + return rc; } /***************************************************************************** -- GitLab From b48a485884b5afb3e33b1871bcbd246b67491923 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 25 Jun 2009 00:56:54 -0400 Subject: [PATCH 0146/1002] cifs: fix problems with earlier patches cifs: fix problems with earlier patches cifs_show_address hasn't been introduced yet, and fix a typo that was silently fixed by a later patch in the series. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ddef913ff3e67..b5e9f398c2e58 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -374,8 +374,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) if (tcon->ses->domainName) seq_printf(s, ",domain=%s", tcon->ses->domainName); - cifs_show_address(s, tcon->ses->server); - seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) seq_printf(s, ",forceuid"); -- GitLab From 6459340cfcc6f6d165b27c3dd955aeb55a1b73d3 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 25 Jun 2009 00:56:55 -0400 Subject: [PATCH 0147/1002] cifs: remove rw/ro options cifs: remove rw/ro options These options are handled at the VFS layer. They only ever set the option in the smb_vol struct. Nothing was ever done with them afterward anyway. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/connect.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 3fb799ff55c9f..a581cfa2ba824 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -70,7 +70,6 @@ struct smb_vol { mode_t file_mode; mode_t dir_mode; unsigned secFlg; - bool rw:1; bool retry:1; bool intr:1; bool setuids:1; @@ -832,7 +831,6 @@ cifs_parse_mount_options(char *options, const char *devname, vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ - vol->rw = true; /* default is always to request posix paths. */ vol->posix_paths = 1; /* default to using server inode numbers where available */ @@ -1198,8 +1196,6 @@ cifs_parse_mount_options(char *options, const char *devname, /* ignore */ } else if (strnicmp(data, "guest", 5) == 0) { /* ignore */ - } else if (strnicmp(data, "rw", 2) == 0) { - vol->rw = true; } else if (strnicmp(data, "noblocksend", 11) == 0) { vol->noblocksnd = 1; } else if (strnicmp(data, "noautotune", 10) == 0) { @@ -1218,8 +1214,6 @@ cifs_parse_mount_options(char *options, const char *devname, parse these options again and set anything and it is ok to just ignore them */ continue; - } else if (strnicmp(data, "ro", 2) == 0) { - vol->rw = false; } else if (strnicmp(data, "hard", 4) == 0) { vol->retry = 1; } else if (strnicmp(data, "soft", 4) == 0) { -- GitLab From 6debdbc0ba6253ac519cd5a3d22e30f1f9f1dd12 Mon Sep 17 00:00:00 2001 From: Simo Leone <simo@archlinux.org> Date: Thu, 25 Jun 2009 02:44:43 +0000 Subject: [PATCH 0148/1002] [CIFS] Copy struct *after* setting the port, instead of before. Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Simo Leone <simo@archlinux.org> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a581cfa2ba824..12c2cf693555a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1496,14 +1496,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info) cFYI(1, ("attempting ipv6 connect")); /* BB should we allow ipv6 on port 139? */ /* other OS never observed in Wild doing 139 with v6 */ + sin_server6->sin6_port = htons(volume_info->port); memcpy(&tcp_ses->addr.sockAddr6, sin_server6, sizeof(struct sockaddr_in6)); - sin_server6->sin6_port = htons(volume_info->port); rc = ipv6_connect(tcp_ses); } else { + sin_server->sin_port = htons(volume_info->port); memcpy(&tcp_ses->addr.sockAddr, sin_server, sizeof(struct sockaddr_in)); - sin_server->sin_port = htons(volume_info->port); rc = ipv4_connect(tcp_ses); } if (rc < 0) { -- GitLab From f46c7234e472ceee39afea4fb5a4365843e1850a Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Thu, 25 Jun 2009 03:04:20 +0000 Subject: [PATCH 0149/1002] [CIFS] cleanup asn handling for ntlmssp Also removes obsolete distinction between rawntlmssp and ntlmssp (in asn/SPNEGO) since as jra noted we can always send raw ntlmssp in session setup now. remove check for experimental runtime flag (/proc/fs/cifs/Experimental) in ntlmssp path. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/asn1.c | 55 +++++++++++++++++++++++++++++++++++++++++----- fs/cifs/cifsglob.h | 2 +- fs/cifs/cifssmb.c | 2 +- fs/cifs/sess.c | 2 +- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 1b09f16700616..20692fbfdb244 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -49,6 +49,7 @@ #define ASN1_OJI 6 /* Object Identifier */ #define ASN1_OJD 7 /* Object Description */ #define ASN1_EXT 8 /* External */ +#define ASN1_ENUM 10 /* Enumerated */ #define ASN1_SEQ 16 /* Sequence */ #define ASN1_SET 17 /* Set */ #define ASN1_NUMSTR 18 /* Numerical String */ @@ -78,10 +79,12 @@ #define SPNEGO_OID_LEN 7 #define NTLMSSP_OID_LEN 10 #define KRB5_OID_LEN 7 +#define KRB5U2U_OID_LEN 8 #define MSKRB5_OID_LEN 7 static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; +static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 }; static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; /* @@ -122,6 +125,28 @@ asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) return 1; } +#if 0 /* will be needed later by spnego decoding/encoding of ntlmssp */ +static unsigned char +asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val) +{ + unsigned char ch; + + if (ctx->pointer >= ctx->end) { + ctx->error = ASN1_ERR_DEC_EMPTY; + return 0; + } + + ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */ + if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */ + *val = *(++(ctx->pointer)); /* value has enum value */ + else + return 0; + + ctx->pointer++; + return 1; +} +#endif + static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) { @@ -476,10 +501,9 @@ decode_negTokenInit(unsigned char *security_blob, int length, unsigned int cls, con, tag, oidlen, rc; bool use_ntlmssp = false; bool use_kerberos = false; + bool use_kerberosu2u = false; bool use_mskerberos = false; - *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ - /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ asn1_open(&ctx, security_blob, length); @@ -515,6 +539,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } + /* SPNEGO */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding negTokenInit")); return 0; @@ -526,6 +551,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } + /* negTokenInit */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding negTokenInit")); return 0; @@ -537,6 +563,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } + /* sequence */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding 2nd part of negTokenInit")); return 0; @@ -548,6 +575,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } + /* sequence of */ if (asn1_header_decode (&ctx, &sequence_end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding 2nd part of negTokenInit")); @@ -560,6 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } + /* list of security mechanisms */ while (!asn1_eoc_decode(&ctx, sequence_end)) { rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); if (!rc) { @@ -576,11 +605,15 @@ decode_negTokenInit(unsigned char *security_blob, int length, if (compare_oid(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN) && - !use_kerberos) + !use_mskerberos) use_mskerberos = true; + else if (compare_oid(oid, oidlen, KRB5U2U_OID, + KRB5U2U_OID_LEN) && + !use_kerberosu2u) + use_kerberosu2u = true; else if (compare_oid(oid, oidlen, KRB5_OID, KRB5_OID_LEN) && - !use_mskerberos) + !use_kerberos) use_kerberos = true; else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) @@ -593,7 +626,12 @@ decode_negTokenInit(unsigned char *security_blob, int length, } } + /* mechlistMIC */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { + /* Check if we have reached the end of the blob, but with + no mechListMic (e.g. NTLMSSP instead of KRB5) */ + if (ctx.error == ASN1_ERR_DEC_EMPTY) + goto decode_negtoken_exit; cFYI(1, ("Error decoding last part negTokenInit exit3")); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { @@ -602,6 +640,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, cls, con, tag, end, *end)); return 0; } + + /* sequence */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding last part negTokenInit exit5")); return 0; @@ -611,6 +651,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, cls, con, tag, end, *end)); } + /* sequence of */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding last part negTokenInit exit 7")); return 0; @@ -619,6 +660,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, cls, con, tag, end, *end)); return 0; } + + /* general string */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { cFYI(1, ("Error decoding last part negTokenInit exit9")); return 0; @@ -630,13 +673,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, } cFYI(1, ("Need to call asn1_octets_decode() function for %s", ctx.pointer)); /* is this UTF-8 or ASCII? */ - +decode_negtoken_exit: if (use_kerberos) *secType = Kerberos; else if (use_mskerberos) *secType = MSKerberos; else if (use_ntlmssp) - *secType = NTLMSSP; + *secType = RawNTLMSSP; return 1; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a61ab772c6f63..e1225e6ded2fc 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -83,7 +83,7 @@ enum securityEnum { NTLM, /* Legacy NTLM012 auth with NTLM hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ - NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */ +/* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */ Kerberos, /* Kerberos via SPNEGO */ MSKerberos, /* MS Kerberos via SPNEGO */ }; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 58d65a9a79c3b..61007c6274975 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) else if (secFlags & CIFSSEC_MAY_KRB5) server->secType = Kerberos; else if (secFlags & CIFSSEC_MAY_NTLMSSP) - server->secType = NTLMSSP; + server->secType = RawNTLMSSP; else if (secFlags & CIFSSEC_MAY_LANMAN) server->secType = LANMAN; /* #ifdef CONFIG_CIFS_EXPERIMENTAL diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 897a052270f90..7085a6275c4c9 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -802,7 +802,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, #endif /* CONFIG_CIFS_UPCALL */ } else { #ifdef CONFIG_CIFS_EXPERIMENTAL - if ((experimEnabled > 1) && (type == RawNTLMSSP)) { + if (type == RawNTLMSSP) { if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { cERROR(1, ("NTLMSSP requires Unicode support")); rc = -ENOSYS; -- GitLab From febe8345353e8873e43f2c2c9792d062c770b22b Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Thu, 25 Jun 2009 14:41:57 +0900 Subject: [PATCH 0150/1002] perf_counter tools: add cpu_relax()/rmb() definitions for sh. Simple cpu_relax()/rmb() stubs that perf needs, which were inadvertently omitted from the sh HAVE_PERF_COUNTERS patch. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- tools/perf/perf.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/perf.h b/tools/perf/perf.h index ceb68aa51f7f5..f735b6924a2f2 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -19,6 +19,16 @@ #define cpu_relax() asm volatile("" ::: "memory"); #endif +#ifdef __sh__ +#include "../../arch/sh/include/asm/unistd.h" +#if defined(__SH4A__) || defined(__SH5__) +# define rmb() asm volatile("synco" ::: "memory") +#else +# define rmb() asm volatile("" ::: "memory") +#endif +#define cpu_relax() asm volatile("" ::: "memory") +#endif + #include <time.h> #include <unistd.h> #include <sys/types.h> -- GitLab From 261c2407401ca26fa17f05667ea68f51e12c5303 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 25 Jun 2009 08:13:40 +0200 Subject: [PATCH 0151/1002] ALSA: hda - Add pin-sense trigger when needed for Realtek codecs Realtek codecs require the pin-sense trigger call before actually reading the pin-sense. Without this, the pin-detection might not be done accurately. This patch adds the pin-capability check and issues the trigger call if required. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3345331974250..98ac24adf39cf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -945,12 +945,13 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, static void alc_automute_pin(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - unsigned int present; + unsigned int present, pincap; unsigned int nid = spec->autocfg.hp_pins[0]; int i; - /* need to execute and sync at first */ - snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); + pincap = snd_hda_query_pin_caps(codec, nid); + if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ + snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); present = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0; @@ -1392,7 +1393,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { static void alc_automute_amp(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - unsigned int val, mute; + unsigned int val, mute, pincap; hda_nid_t nid; int i; @@ -1401,6 +1402,10 @@ static void alc_automute_amp(struct hda_codec *codec) nid = spec->autocfg.hp_pins[i]; if (!nid) break; + pincap = snd_hda_query_pin_caps(codec, nid); + if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ + snd_hda_codec_read(codec, nid, 0, + AC_VERB_SET_PIN_SENSE, 0); val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); if (val & AC_PINSENSE_PRESENCE) { -- GitLab From 320d592001acbfd76bf856b5370319f144285489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <buhitoescolar@gmail.com> Date: Thu, 25 Jun 2009 08:18:44 +0200 Subject: [PATCH 0152/1002] ALSA: hda - Fix acer-aspire-6530g model quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following bugs of acer-aspire-6530g model with ALC888: - HP jack to mute all speaker outputs including LFE - Make digital built-in mic working Signed-off-by: Emilio López <buhitoescolar@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 98ac24adf39cf..7ebe5216b4b59 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1476,6 +1476,10 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { /* Bias voltage on for external mic port */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80}, +/* Front Mic: set to PIN_IN (empty by default) */ + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, +/* Unselect Front Mic by default in input mixer 3 */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)}, /* Enable unsolicited event for HP jack */ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, /* Enable speaker output */ @@ -1644,6 +1648,17 @@ static void alc888_acer_aspire_4930g_init_hook(struct hda_codec *codec) alc_automute_amp(codec); } +static void alc888_acer_aspire_6530g_init_hook(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; + spec->autocfg.speaker_pins[1] = 0x16; + spec->autocfg.speaker_pins[2] = 0x17; + alc_automute_amp(codec); +} + static void alc889_acer_aspire_8930g_init_hook(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -9322,7 +9337,7 @@ static struct alc_config_preset alc883_presets[] = { ARRAY_SIZE(alc888_2_capture_sources), .input_mux = alc888_acer_aspire_6530_sources, .unsol_event = alc_automute_amp_unsol_event, - .init_hook = alc888_acer_aspire_4930g_init_hook, + .init_hook = alc888_acer_aspire_6530g_init_hook, }, [ALC888_ACER_ASPIRE_8930G] = { .mixers = { alc888_base_mixer, -- GitLab From dde6535686aa4e78e8b85850d1f3fccd8a581622 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 25 Jun 2009 08:25:35 +0200 Subject: [PATCH 0153/1002] ALSA: hda - Use model=acer-aspire-6530g for Acer Aspire 6930G For Acer Aspire 6930G (1025:015e), acre-aspire-6530g model matches obviously better. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7ebe5216b4b59..2ed514030e75e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9084,7 +9084,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC883_AUTO), SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC883_AUTO), SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", - ALC888_ACER_ASPIRE_4930G), + ALC888_ACER_ASPIRE_6530G), SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", ALC888_ACER_ASPIRE_6530G), /* default Acer -- disabled as it causes more problems. -- GitLab From 28d27aae9432c300857722a917be4065c6d7abff Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Wed, 24 Jun 2009 22:13:35 -0700 Subject: [PATCH 0154/1002] sound: Use PCI_VDEVICE Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/oss/kahlua.c | 2 +- sound/pci/atiixp.c | 8 +++---- sound/pci/atiixp_modem.c | 4 ++-- sound/pci/au88x0/au8810.c | 3 +-- sound/pci/au88x0/au8820.c | 3 +-- sound/pci/au88x0/au8830.c | 3 +-- sound/pci/cmipci.c | 10 ++++---- sound/pci/cs4281.c | 2 +- sound/pci/cs46xx/cs46xx.c | 6 ++--- sound/pci/ens1370.c | 6 ++--- sound/pci/es1938.c | 2 +- sound/pci/ice1712/ice1712.c | 2 +- sound/pci/ice1712/ice1724.c | 2 +- sound/pci/intel8x0.c | 46 ++++++++++++++++++------------------- sound/pci/intel8x0m.c | 34 +++++++++++++-------------- sound/pci/mixart/mixart.c | 2 +- sound/pci/nm256/nm256.c | 6 ++--- sound/pci/rme32.c | 9 +++----- sound/pci/rme96.c | 12 ++++------ sound/pci/sonicvibes.c | 2 +- sound/pci/via82xx.c | 4 ++-- sound/pci/via82xx_modem.c | 2 +- sound/pci/ymfpci/ymfpci.c | 12 +++++----- 23 files changed, 86 insertions(+), 96 deletions(-) diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c index c180598f17104..89466b056be79 100644 --- a/sound/oss/kahlua.c +++ b/sound/oss/kahlua.c @@ -199,7 +199,7 @@ MODULE_LICENSE("GPL"); */ static struct pci_device_id id_tbl[] = { - { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 }, { } }; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 71515ddb4593c..d6752dff2a443 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -287,10 +287,10 @@ struct atiixp { /* */ static struct pci_device_id snd_atiixp_ids[] = { - { 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ - { 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */ - { 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ - { 0x1002, 0x4382, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB600 */ + { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */ + { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */ + { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */ + { PCI_VDEVICE(ATI, 0x4382), 0 }, /* SB600 */ { 0, } }; diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c3136cccc559e..e7e147bf8eb26 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -262,8 +262,8 @@ struct atiixp_modem { /* */ static struct pci_device_id snd_atiixp_ids[] = { - { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ - { 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ + { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */ + { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */ { 0, } }; diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c index fce22c7af0ea2..c0e8c6b295cb9 100644 --- a/sound/pci/au88x0/au8810.c +++ b/sound/pci/au88x0/au8810.c @@ -1,8 +1,7 @@ #include "au8810.h" #include "au88x0.h" static struct pci_device_id snd_vortex_ids[] = { - {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1,}, + {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,}, {0,} }; diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c index d1fbcce072573..a6527330df584 100644 --- a/sound/pci/au88x0/au8820.c +++ b/sound/pci/au88x0/au8820.c @@ -1,8 +1,7 @@ #include "au8820.h" #include "au88x0.h" static struct pci_device_id snd_vortex_ids[] = { - {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, + {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), 0,}, {0,} }; diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c index d4f2717c14fb0..6c702ad4352ad 100644 --- a/sound/pci/au88x0/au8830.c +++ b/sound/pci/au88x0/au8830.c @@ -1,8 +1,7 @@ #include "au8830.h" #include "au88x0.h" static struct pci_device_id snd_vortex_ids[] = { - {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, + {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), 0,}, {0,} }; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 449fe02f666e1..ddcd4a9fd7e69 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2797,11 +2797,11 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {} static struct pci_device_id snd_cmipci_ids[] = { - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0}, + {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, {0,}, }; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index f6286f84a2213..e2e0359bb0568 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -495,7 +495,7 @@ struct cs4281 { static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); static struct pci_device_id snd_cs4281_ids[] = { - { 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4281 */ + { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */ { 0, } }; diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index c9b3e3d48cbcb..033aec430117a 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -65,9 +65,9 @@ module_param_array(mmap_valid, bool, NULL, 0444); MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); static struct pci_device_id snd_cs46xx_ids[] = { - { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */ - { 0x1013, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4612 */ - { 0x1013, 0x6004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4615 */ + { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */ + { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */ + { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */ { 0, } }; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 18f4d1e98c469..d589bbc516e20 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -445,11 +445,11 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id); static struct pci_device_id snd_audiopci_ids[] = { #ifdef CHIP1370 - { 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1370 */ + { PCI_VDEVICE(ENSONIQ, 0x5000), 0, }, /* ES1370 */ #endif #ifdef CHIP1371 - { 0x1274, 0x1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1371 */ - { 0x1274, 0x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1373 - CT5880 */ + { PCI_VDEVICE(ENSONIQ, 0x1371), 0, }, /* ES1371 */ + { PCI_VDEVICE(ENSONIQ, 0x5880), 0, }, /* ES1373 - CT5880 */ { 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ectiva EV1938 */ #endif { 0, } diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index fbd2ac09aa34a..820318ee62c17 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -244,7 +244,7 @@ struct es1938 { static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id); static struct pci_device_id snd_es1938_ids[] = { - { 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Solo-1 */ + { PCI_VDEVICE(ESS, 0x1969), 0, }, /* Solo-1 */ { 0, } }; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 0d0cdbdb44867..cecf1ffeeaaa4 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -107,7 +107,7 @@ MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); static const struct pci_device_id snd_ice1712_ids[] = { - { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */ + { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 }, /* ICE1712 */ { 0, } }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 36ade77cf3711..cc84a831eb21f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -93,7 +93,7 @@ MODULE_PARM_DESC(model, "Use the given board model."); /* Both VT1720 and VT1724 have the same PCI IDs */ static const struct pci_device_id snd_vt1724_ids[] = { - { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 }, { 0, } }; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 8aa5687f392a1..171ada535209a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -421,29 +421,29 @@ struct intel8x0 { }; static struct pci_device_id snd_intel8x0_ids[] = { - { 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */ - { 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */ - { 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */ - { 0x8086, 0x2485, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */ - { 0x8086, 0x24c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH4 */ - { 0x8086, 0x24d5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH5 */ - { 0x8086, 0x25a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB */ - { 0x8086, 0x266e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH6 */ - { 0x8086, 0x27de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH7 */ - { 0x8086, 0x2698, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB2 */ - { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */ - { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7012 */ - { 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */ - { 0x10de, 0x003a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* MCP04 */ - { 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */ - { 0x10de, 0x0059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK804 */ - { 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8 */ - { 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */ - { 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8S */ - { 0x10de, 0x026b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* MCP51 */ - { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ - { 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ - { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ + { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */ + { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */ + { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */ + { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL }, /* ICH3 */ + { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */ + { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */ + { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */ + { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */ + { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */ + { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */ + { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL }, /* 440MX */ + { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS }, /* SI7012 */ + { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */ + { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */ + { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */ + { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */ + { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */ + { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */ + { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */ + { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */ + { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ + { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL }, /* AMD768 */ + { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ { 0, } }; diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 6ec0fc50d6be1..9e7d12e7673f5 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -220,24 +220,24 @@ struct intel8x0m { }; static struct pci_device_id snd_intel8x0m_ids[] = { - { 0x8086, 0x2416, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */ - { 0x8086, 0x2426, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */ - { 0x8086, 0x2446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */ - { 0x8086, 0x2486, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */ - { 0x8086, 0x24c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH4 */ - { 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */ - { 0x8086, 0x266d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH6 */ - { 0x8086, 0x27dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH7 */ - { 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */ - { 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ - { 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7013 */ - { 0x10de, 0x01c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */ - { 0x10de, 0x0069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */ - { 0x10de, 0x0089, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2s */ - { 0x10de, 0x00d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */ + { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL }, /* 82801AA */ + { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL }, /* 82901AB */ + { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL }, /* 82801BA */ + { PCI_VDEVICE(INTEL, 0x2486), DEVICE_INTEL }, /* ICH3 */ + { PCI_VDEVICE(INTEL, 0x24c6), DEVICE_INTEL }, /* ICH4 */ + { PCI_VDEVICE(INTEL, 0x24d6), DEVICE_INTEL }, /* ICH5 */ + { PCI_VDEVICE(INTEL, 0x266d), DEVICE_INTEL }, /* ICH6 */ + { PCI_VDEVICE(INTEL, 0x27dd), DEVICE_INTEL }, /* ICH7 */ + { PCI_VDEVICE(INTEL, 0x7196), DEVICE_INTEL }, /* 440MX */ + { PCI_VDEVICE(AMD, 0x7446), DEVICE_INTEL }, /* AMD768 */ + { PCI_VDEVICE(SI, 0x7013), DEVICE_SIS }, /* SI7013 */ + { PCI_VDEVICE(NVIDIA, 0x01c1), DEVICE_NFORCE }, /* NFORCE */ + { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ + { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ + { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ #if 0 - { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ - { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ + { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ + { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ #endif { 0, } }; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 82bc5b9e7629d..a83d1968a8450 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -61,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); */ static struct pci_device_id snd_mixart_ids[] = { - { 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */ + { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */ { 0, } }; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 522a040855d41..97a0731331a15 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -263,9 +263,9 @@ struct nm256 { * PCI ids */ static struct pci_device_id snd_nm256_ids[] = { - {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0}, + {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0}, + {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0}, {0,}, }; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index d7b966e7c4cf6..f977dba7cbd09 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -227,12 +227,9 @@ struct rme32 { }; static struct pci_device_id snd_rme32_ids[] = { - {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, - {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, - {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, + {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,}, + {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,}, + {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,}, {0,} }; diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 55fb1c131f580..2ba5c0fd55dbb 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -232,14 +232,10 @@ struct rme96 { }; static struct pci_device_id snd_rme96_ids[] = { - { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, }, { 0, } }; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 7dc60ad4772e3..1f6406c4534d4 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -243,7 +243,7 @@ struct sonicvibes { }; static struct pci_device_id snd_sonic_ids[] = { - { 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_VDEVICE(S3, 0xca00), 0, }, { 0, } }; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 949fcaf6b70ed..acfa4760da49e 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -402,9 +402,9 @@ struct via82xx { static struct pci_device_id snd_via82xx_ids[] = { /* 0x1106, 0x3058 */ - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, }, /* 686A */ /* 0x1106, 0x3059 */ - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), TYPE_CARD_VIA8233, }, /* VT8233 */ { 0, } }; diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 0d54e3503c1e6..47eb61561dfca 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -261,7 +261,7 @@ struct via82xx_modem { }; static struct pci_device_id snd_via82xx_modem_ids[] = { - { 0x1106, 0x3068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA82XX_MODEM, }, + { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, }, { 0, } }; diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 4af66661f9b02..e6b18b90d4510 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -67,12 +67,12 @@ module_param_array(rear_switch, bool, NULL, 0444); MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); static struct pci_device_id snd_ymfpci_ids[] = { - { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */ - { 0x1073, 0x000d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724F */ - { 0x1073, 0x000a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF740 */ - { 0x1073, 0x000c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF740C */ - { 0x1073, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF744 */ - { 0x1073, 0x0012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF754 */ + { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */ + { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */ + { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */ + { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */ + { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */ + { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */ { 0, } }; -- GitLab From 0d7392e54435476243ce08ba57745ab52d639cbb Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Wed, 24 Jun 2009 23:18:02 -0700 Subject: [PATCH 0155/1002] sound: Use PCI_VDEVICE for CREATIVE and ECTIVA Here's a patch on top of the others to use CREATIVE and ECTIVA Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/ca0106/ca0106_main.c | 2 +- sound/pci/emu10k1/emu10k1.c | 6 +++--- sound/pci/emu10k1/emu10k1x.c | 2 +- sound/pci/ens1370.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 57b992a5c0572..f24bf1ecb36d1 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1876,7 +1876,7 @@ static int snd_ca0106_resume(struct pci_dev *pci) // PCI IDs static struct pci_device_id snd_ca0106_ids[] = { - { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */ + { PCI_VDEVICE(CREATIVE, 0x0007), 0 }, /* Audigy LS or Live 24bit */ { 0, } }; MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index c7f3b994101ce..168af67d938e1 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -77,9 +77,9 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ static struct pci_device_id snd_emu10k1_ids[] = { - { 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */ - { 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */ - { 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */ + { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ + { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ + { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ { 0, } }; diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 4d3ad793e98fb..36e08bd2b3cc6 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1607,7 +1607,7 @@ static void __devexit snd_emu10k1x_remove(struct pci_dev *pci) // PCI IDs static struct pci_device_id snd_emu10k1x_ids[] = { - { 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dell OEM version (EMU10K1) */ + { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ { 0, } }; MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index d589bbc516e20..2b82c5c723e15 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -450,7 +450,7 @@ static struct pci_device_id snd_audiopci_ids[] = { #ifdef CHIP1371 { PCI_VDEVICE(ENSONIQ, 0x1371), 0, }, /* ES1371 */ { PCI_VDEVICE(ENSONIQ, 0x5880), 0, }, /* ES1373 - CT5880 */ - { 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ectiva EV1938 */ + { PCI_VDEVICE(ECTIVA, 0x8938), 0, }, /* Ectiva EV1938 */ #endif { 0, } }; -- GitLab From 342ba1039ad7cf464c7927ddf1ddc10d48a3716b Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Wed, 24 Jun 2009 18:39:09 -0300 Subject: [PATCH 0156/1002] mtd: cmdlineparts: Use 64-bit format when printing a debug message. Commit 69423d99fc182a81f3c5db3eb5c140acc6fc64be ("[MTD] update internal API to support 64-bit device size") has changed some structure values to 64-bit and has not updated this debug message, since it's not built by default. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/mtd/cmdlinepart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 5011fa73f9188..1479da6d3aa6d 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -194,7 +194,7 @@ static struct mtd_partition * newpart(char *s, parts[this_part].name = extra_mem; extra_mem += name_len + 1; - dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n", + dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n", this_part, parts[this_part].name, parts[this_part].offset, -- GitLab From ae27a7ab2c74f9c075e03730c5f493163d048c62 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Wed, 24 Jun 2009 18:40:46 -0300 Subject: [PATCH 0157/1002] mtd: atmel_nand: Fix typo s/parititions/partitions/ Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/mtd/nand/atmel_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2802992b39daf..20c828ba94052 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) &num_partitions); if ((!partitions) || (num_partitions == 0)) { - printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n"); + printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n"); res = ENXIO; goto err_no_partitions; } -- GitLab From 7e895cfaad51c862932ea7db0c428761076412e5 Mon Sep 17 00:00:00 2001 From: Tim Blechmann <tim@klingt.org> Date: Thu, 25 Jun 2009 09:41:46 +0200 Subject: [PATCH 0158/1002] ALSA: lx6464es - configure ethersound io channels as long as the io channel number is not set by the driver, the card is not visible from the ethersound network Signed-off-by: Tim Blechmann <tim@klingt.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/lx6464es/lx6464es.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 18da2ef04d097..11b8c6514b3d8 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -654,13 +654,12 @@ static int __devinit lx_init_ethersound_config(struct lx6464es *chip) int i; u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES); - u32 default_conf_es = (64 << IOCR_OUTPUTS_OFFSET) | + /* configure 64 io channels */ + u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK) | (64 << IOCR_INPUTS_OFFSET) | + (64 << IOCR_OUTPUTS_OFFSET) | (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET); - u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK) - | (default_conf_es & CONFES_WRITE_PART_MASK); - snd_printdd("->lx_init_ethersound\n"); chip->freq_ratio = FREQ_RATIO_SINGLE_MODE; -- GitLab From 00e54d087afb3867b0b461aef6c1ff433d0df564 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Thu, 25 Jun 2009 14:05:27 +0800 Subject: [PATCH 0159/1002] ftrace: Remove duplicate newline Before: # echo 'sys_open:traceon:' > set_ftrace_filter # echo 'sys_close:traceoff:5' > set_ftrace_filter # cat set_ftrace_filter #### all functions enabled #### sys_open:traceon:unlimited sys_close:traceoff:count=0 After: # cat set_ftrace_filter #### all functions enabled #### sys_open:traceon:unlimited sys_close:traceoff:count=0 Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A4313A7.7030105@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_functions.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index 90f134764837e..7402144bff218 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c @@ -302,8 +302,7 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, if (count == -1) seq_printf(m, ":unlimited\n"); else - seq_printf(m, ":count=%ld", count); - seq_putc(m, '\n'); + seq_printf(m, ":count=%ld\n", count); return 0; } -- GitLab From 1155de47cd66d0c496d5a6fb2223e980ef1285b2 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Thu, 25 Jun 2009 14:30:12 +0900 Subject: [PATCH 0160/1002] ring-buffer: Make it generally available In hunting down the cause for the hwlat_detector ring buffer spew in my failed -next builds it became obvious that folks are now treating ring_buffer as something that is generic independent of tracing and thus, suitable for public driver consumption. Given that there are only a few minor areas in ring_buffer that have any reliance on CONFIG_TRACING or CONFIG_FUNCTION_TRACER, provide stubs for those and make it generally available. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Cc: Jon Masters <jcm@jonmasters.org> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <20090625053012.GB19944@linux-sh.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/Makefile | 1 + kernel/trace/ring_buffer.c | 11 +++++++++++ kernel/trace/trace.h | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/kernel/Makefile b/kernel/Makefile index 0a32cb21ec975..0630e293cd493 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o obj-$(CONFIG_FUNCTION_TRACER) += trace/ obj-$(CONFIG_TRACING) += trace/ obj-$(CONFIG_X86_DS) += trace/ +obj-$(CONFIG_RING_BUFFER) += trace/ obj-$(CONFIG_SMP) += sched_cpupri.o obj-$(CONFIG_SLOW_WORK) += slow-work.o obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 04dac26382587..bf27bb7a63e2d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1563,6 +1563,8 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, return NULL; } +#ifdef CONFIG_TRACING + #define TRACE_RECURSIVE_DEPTH 16 static int trace_recursive_lock(void) @@ -1593,6 +1595,13 @@ static void trace_recursive_unlock(void) current->trace_recursion--; } +#else + +#define trace_recursive_lock() (0) +#define trace_recursive_unlock() do { } while (0) + +#endif + static DEFINE_PER_CPU(int, rb_need_resched); /** @@ -3104,6 +3113,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer, } EXPORT_SYMBOL_GPL(ring_buffer_read_page); +#ifdef CONFIG_TRACING static ssize_t rb_simple_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -3171,6 +3181,7 @@ static __init int rb_init_debugfs(void) } fs_initcall(rb_init_debugfs); +#endif #ifdef CONFIG_HOTPLUG_CPU static int rb_cpu_notify(struct notifier_block *self, diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 6e735d4771f8a..3548ae5cc7801 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -597,6 +597,7 @@ print_graph_function(struct trace_iterator *iter) extern struct pid *ftrace_pid_trace; +#ifdef CONFIG_FUNCTION_TRACER static inline int ftrace_trace_task(struct task_struct *task) { if (!ftrace_pid_trace) @@ -604,6 +605,12 @@ static inline int ftrace_trace_task(struct task_struct *task) return test_tsk_trace_trace(task); } +#else +static inline int ftrace_trace_task(struct task_struct *task) +{ + return 1; +} +#endif /* * trace_iterator_flags is an enumeration that defines bit -- GitLab From a9d9058abab4ac17b79d500506e6c74bd16cecdc Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Thu, 25 Jun 2009 10:16:11 +0100 Subject: [PATCH 0161/1002] kmemleak: Allow the early log buffer to be configurable. (feature suggested by Sergey Senozhatsky) Kmemleak needs to track all the memory allocations but some of these happen before kmemleak is initialised. These are stored in an internal buffer which may be exceeded in some kernel configurations. This patch adds a configuration option with a default value of 400 and also removes the stack dump when the early log buffer is exceeded. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Sergey Senozhatsky <sergey.senozhatsky@mail.by> --- Documentation/kmemleak.txt | 4 ++++ lib/Kconfig.debug | 12 ++++++++++++ mm/kmemleak.c | 5 +++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index 0112da3b9ab87..f655308064d76 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -41,6 +41,10 @@ Memory scanning parameters can be modified at run-time by writing to the Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on the kernel command line. +Memory may be allocated or freed before kmemleak is initialised and +these actions are stored in an early log buffer. The size of this buffer +is configured via the CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE option. + Basic Algorithm --------------- diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 4c32b1a1a06e3..12327b2bb785c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -359,6 +359,18 @@ config DEBUG_KMEMLEAK In order to access the kmemleak file, debugfs needs to be mounted (usually at /sys/kernel/debug). +config DEBUG_KMEMLEAK_EARLY_LOG_SIZE + int "Maximum kmemleak early log entries" + depends on DEBUG_KMEMLEAK + range 200 2000 + default 400 + help + Kmemleak must track all the memory allocations to avoid + reporting false positives. Since memory may be allocated or + freed before kmemleak is initialised, an early log buffer is + used to store these actions. If kmemleak reports "early log + buffer exceeded", please increase this value. + config DEBUG_KMEMLEAK_TEST tristate "Simple test for the kernel memory leak detector" depends on DEBUG_KMEMLEAK diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c96f2c8700aa6..17096d1b59b27 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -235,7 +235,7 @@ struct early_log { }; /* early logging buffer and current position */ -static struct early_log early_log[200]; +static struct early_log early_log[CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE]; static int crt_early_log; static void kmemleak_disable(void); @@ -696,7 +696,8 @@ static void log_early(int op_type, const void *ptr, size_t size, struct early_log *log; if (crt_early_log >= ARRAY_SIZE(early_log)) { - kmemleak_stop("Early log buffer exceeded\n"); + pr_warning("Early log buffer exceeded\n"); + kmemleak_disable(); return; } -- GitLab From 76c64c5e4c47b6d28deb3cae8dfa07a93c2229dc Mon Sep 17 00:00:00 2001 From: Johannes Weiner <hannes@cmpxchg.org> Date: Wed, 24 Jun 2009 21:08:36 +0200 Subject: [PATCH 0162/1002] perf record: Fix filemap pathname parsing in /proc/pid/maps Looking backward for the first space from the end of a line in /proc/pid/maps does not find the start of the pathname of the mapped file if it contains a space. Since the only slashes we have in this file occur in the (absolute!) pathname column of file mappings, looking for the first slash in a line is a safe method to find the name. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Stefani Seibold <stefani@seibold.net> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20090624190835.GA25548@cmpxchg.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-record.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d7ebbd7575432..9b899ba1b4108 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -306,12 +306,11 @@ static void pid_synthesize_mmap_samples(pid_t pid) continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ - char *execname = strrchr(bf, ' '); + char *execname = strchr(bf, '/'); - if (execname == NULL || execname[1] != '/') + if (execname == NULL) continue; - execname += 1; size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(mmap_ev.filename, execname, size); -- GitLab From 11687a1099583273a8a98ec42af62b5bb5a69e45 Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Thu, 25 Jun 2009 02:45:42 -0700 Subject: [PATCH 0163/1002] Revert "veth: prevent oops caused by netdev destructor" This reverts commit ae0e8e82205c903978a79ebf5e31c670b61fa5b4. This change had two problems: 1) Since it frees the stats in the drivers' close method, we can OOPS in the transmit routine. 2) stats are no longer remembered across ifdown/ifup which disagrees with how every other device operates. Thanks to analysis and test patch from Serge E. Hallyn and initial OOPS report by Sachin Sant. Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/veth.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 87197dd9c7884..1097c72e44d5b 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -208,11 +208,14 @@ static int veth_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *veth_get_stats(struct net_device *dev) { - struct veth_priv *priv = netdev_priv(dev); - struct net_device_stats *dev_stats = &dev->stats; - unsigned int cpu; + struct veth_priv *priv; + struct net_device_stats *dev_stats; + int cpu; struct veth_net_stats *stats; + priv = netdev_priv(dev); + dev_stats = &dev->stats; + dev_stats->rx_packets = 0; dev_stats->tx_packets = 0; dev_stats->rx_bytes = 0; @@ -220,17 +223,16 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) dev_stats->tx_dropped = 0; dev_stats->rx_dropped = 0; - if (priv->stats) - for_each_online_cpu(cpu) { - stats = per_cpu_ptr(priv->stats, cpu); + for_each_online_cpu(cpu) { + stats = per_cpu_ptr(priv->stats, cpu); - dev_stats->rx_packets += stats->rx_packets; - dev_stats->tx_packets += stats->tx_packets; - dev_stats->rx_bytes += stats->rx_bytes; - dev_stats->tx_bytes += stats->tx_bytes; - dev_stats->tx_dropped += stats->tx_dropped; - dev_stats->rx_dropped += stats->rx_dropped; - } + dev_stats->rx_packets += stats->rx_packets; + dev_stats->tx_packets += stats->tx_packets; + dev_stats->rx_bytes += stats->rx_bytes; + dev_stats->tx_bytes += stats->tx_bytes; + dev_stats->tx_dropped += stats->tx_dropped; + dev_stats->rx_dropped += stats->rx_dropped; + } return dev_stats; } @@ -257,8 +259,6 @@ static int veth_close(struct net_device *dev) netif_carrier_off(dev); netif_carrier_off(priv->peer); - free_percpu(priv->stats); - priv->stats = NULL; return 0; } @@ -289,6 +289,15 @@ static int veth_dev_init(struct net_device *dev) return 0; } +static void veth_dev_free(struct net_device *dev) +{ + struct veth_priv *priv; + + priv = netdev_priv(dev); + free_percpu(priv->stats); + free_netdev(dev); +} + static const struct net_device_ops veth_netdev_ops = { .ndo_init = veth_dev_init, .ndo_open = veth_open, @@ -306,7 +315,7 @@ static void veth_setup(struct net_device *dev) dev->netdev_ops = &veth_netdev_ops; dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; - dev->destructor = free_netdev; + dev->destructor = veth_dev_free; } /* -- GitLab From c7a1a4c80f873d5d6ecd173035bb80eba489f380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= <remi.denis-courmont@nokia.com> Date: Wed, 24 Jun 2009 01:07:44 +0000 Subject: [PATCH 0164/1002] Phonet: publicize the Netlink notification function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- include/net/phonet/pn_dev.h | 1 + net/phonet/pn_netlink.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 5054dc5ea2c26..29d126736611c 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h @@ -45,6 +45,7 @@ int phonet_address_add(struct net_device *dev, u8 addr); int phonet_address_del(struct net_device *dev, u8 addr); u8 phonet_address_get(struct net_device *dev, u8 addr); int phonet_address_lookup(struct net *net, u8 addr); +void phonet_address_notify(int event, struct net_device *dev, u8 addr); #define PN_NO_ADDR 0xff diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index cec4e59516817..f8b4cee434c23 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -32,7 +32,7 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, u32 pid, u32 seq, int event); -static void rtmsg_notify(int event, struct net_device *dev, u8 addr) +void phonet_address_notify(int event, struct net_device *dev, u8 addr) { struct sk_buff *skb; int err = -ENOBUFS; @@ -94,7 +94,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr) else err = phonet_address_del(dev, pnaddr); if (!err) - rtmsg_notify(nlh->nlmsg_type, dev, pnaddr); + phonet_address_notify(nlh->nlmsg_type, dev, pnaddr); return err; } -- GitLab From 2be6fa4c7e5731375cc5e70843a3444293c27514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= <remi.denis-courmont@nokia.com> Date: Wed, 24 Jun 2009 01:07:45 +0000 Subject: [PATCH 0165/1002] Phonet: generate Netlink RTM_DELADDR when destroying a device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Netlink address deletion events were not sent when a network device vanished neither when Phonet was unloaded. Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/phonet/pn_dev.c | 52 +++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 80a322d77909a..b0d6ddd82a9da 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -69,10 +69,27 @@ static struct phonet_device *__phonet_get(struct net_device *dev) return NULL; } -static void __phonet_device_free(struct phonet_device *pnd) +static void phonet_device_destroy(struct net_device *dev) { - list_del(&pnd->list); - kfree(pnd); + struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); + struct phonet_device *pnd; + + ASSERT_RTNL(); + + spin_lock_bh(&pndevs->lock); + pnd = __phonet_get(dev); + if (pnd) + list_del(&pnd->list); + spin_unlock_bh(&pndevs->lock); + + if (pnd) { + u8 addr; + + for (addr = find_first_bit(pnd->addrs, 64); addr < 64; + addr = find_next_bit(pnd->addrs, 64, 1+addr)) + phonet_address_notify(RTM_DELADDR, dev, addr); + kfree(pnd); + } } struct net_device *phonet_device_get(struct net *net) @@ -126,8 +143,10 @@ int phonet_address_del(struct net_device *dev, u8 addr) pnd = __phonet_get(dev); if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) err = -EADDRNOTAVAIL; - else if (bitmap_empty(pnd->addrs, 64)) - __phonet_device_free(pnd); + else if (bitmap_empty(pnd->addrs, 64)) { + list_del(&pnd->list); + kfree(pnd); + } spin_unlock_bh(&pndevs->lock); return err; } @@ -181,18 +200,8 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, { struct net_device *dev = arg; - if (what == NETDEV_UNREGISTER) { - struct phonet_device_list *pndevs; - struct phonet_device *pnd; - - /* Destroy phonet-specific device data */ - pndevs = phonet_device_list(dev_net(dev)); - spin_lock_bh(&pndevs->lock); - pnd = __phonet_get(dev); - if (pnd) - __phonet_device_free(pnd); - spin_unlock_bh(&pndevs->lock); - } + if (what == NETDEV_UNREGISTER) + phonet_device_destroy(dev); return 0; } @@ -218,11 +227,12 @@ static int phonet_init_net(struct net *net) static void phonet_exit_net(struct net *net) { struct phonet_net *pnn = net_generic(net, phonet_net_id); - struct phonet_device *pnd, *n; - - list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list) - __phonet_device_free(pnd); + struct net_device *dev; + rtnl_lock(); + for_each_netdev(net, dev) + phonet_device_destroy(dev); + rtnl_unlock(); kfree(pnn); } -- GitLab From d8146bb23ea045fb75c56b4e3b53f0964eed4076 Mon Sep 17 00:00:00 2001 From: Brandon Philips <brandon@ifup.org> Date: Wed, 24 Jun 2009 14:09:14 +0000 Subject: [PATCH 0166/1002] atl1*: add device_set_wakeup_enable to atl1*_set_wol Tell PCI core that atl1* device can wakeup the system when WOL is enabled by calling device_set_wakeup_enable. Joerg noted that his atl1e device WOL fine after enabling it with ethtool and changing /sys/class/net/eth0/device/power/wakeup to enabled Tested on atl1e: https://bugzilla.novell.com/show_bug.cgi?id=493214 Tested by: Joerg Reuter <jreuter@novell.com> Signed-off-by: Brandon Philips <bphilips@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/atl1c/atl1c_ethtool.c | 2 ++ drivers/net/atl1e/atl1e_ethtool.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index e4afbd628c23e..607007d75b6fa 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -281,6 +281,8 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_PHY) adapter->wol |= AT_WUFC_LNKC; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + return 0; } diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index 619c6583e1aac..4003955d7a965 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c @@ -365,6 +365,8 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_PHY) adapter->wol |= AT_WUFC_LNKC; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + return 0; } -- GitLab From 06813f6c743420c16f9248ab59bd2e68a2de57ba Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 25 Jun 2009 17:16:07 +0530 Subject: [PATCH 0167/1002] perf_counter tools: Check for valid cache operations Made new table for cache operartion stat 'hw_cache_stat' as: L1I : Read and prefetch only ITLB and BPU : Read-only introduce is_cache_op_valid() for cache operation validity And checks for valid cache operations. Reported-by : Ingo Molnar <mingo@elte.hu> Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245930367.5308.33.camel@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 06af2fadcd870..7939a21130d2b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -90,6 +90,34 @@ static char *hw_cache_result[][MAX_ALIASES] = { { "Miss" }, }; +#define C(x) PERF_COUNT_HW_CACHE_##x +#define CACHE_READ (1 << C(OP_READ)) +#define CACHE_WRITE (1 << C(OP_WRITE)) +#define CACHE_PREFETCH (1 << C(OP_PREFETCH)) +#define COP(x) (1 << x) + +/* + * cache operartion stat + * L1I : Read and prefetch only + * ITLB and BPU : Read-only + */ +static unsigned long hw_cache_stat[C(MAX)] = { + [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), + [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), + [C(ITLB)] = (CACHE_READ), + [C(BPU)] = (CACHE_READ), +}; + +static int is_cache_op_valid(u8 cache_type, u8 cache_op) +{ + if (hw_cache_stat[cache_type] & COP(cache_op)) + return 1; /* valid */ + else + return 0; /* invalid */ +} + char *event_name(int counter) { u64 config = attrs[counter].config; @@ -123,6 +151,8 @@ char *event_name(int counter) if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) return "unknown-ext-hardware-cache-result"; + if (!is_cache_op_valid(cache_type, cache_op)) + return "invalid-cache"; sprintf(name, "%s-Cache-%s-%ses", hw_cache[cache_type][0], hw_cache_op[cache_op][0], @@ -179,6 +209,9 @@ parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) if (cache_op == -1) cache_op = PERF_COUNT_HW_CACHE_OP_READ; + if (!is_cache_op_valid(cache_type, cache_op)) + return -EINVAL; + cache_result = parse_aliases(str, hw_cache_result, PERF_COUNT_HW_CACHE_RESULT_MAX); /* -- GitLab From 1fbcf37128cc19bd67d9a736fb634dc444e907d7 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Thu, 25 Jun 2009 21:17:19 +0900 Subject: [PATCH 0168/1002] sh: Kill off unused DEBUG_BOOTMEM symbol. This was killed off in generic code some time ago, kill off the left over symbol. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/Kconfig.debug | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 8ece0b5bd0282..39224b57c6efe 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -61,10 +61,6 @@ config EARLY_PRINTK select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using the kernel command line option to toggle back and forth. -config DEBUG_BOOTMEM - depends on DEBUG_KERNEL - bool "Debug BOOTMEM initialization" - config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL && SUPERH32 -- GitLab From aa715284b4d28cabde6c25c568d769a6be712bc8 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner <tglx@linutronix.de> Date: Thu, 25 Jun 2009 14:27:58 +0200 Subject: [PATCH 0169/1002] futex: request only one page from get_user_pages() Yanmin noticed that fault_in_user_writeable() requests 4 pages instead of one. That's the result of blindly trusting Linus' proposal :) I even looked up the prototype to verify the correctness: the argument in question is confusingly enough named "len" while in reality it means number of pages. Pointed-out-by: Yanmin Zhang <yanmin_zhang@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- kernel/futex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/futex.c b/kernel/futex.c index 1c337112335c6..794c862125fef 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -299,7 +299,7 @@ void put_futex_key(int fshared, union futex_key *key) static int fault_in_user_writeable(u32 __user *uaddr) { int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, - sizeof(*uaddr), 1, 0, NULL, NULL); + 1, 1, 0, NULL, NULL); return ret < 0 ? ret : 0; } -- GitLab From dd5e8e6b1d4c218d2bafe002231ec460459ab5c4 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi <peter.ujfalusi@nokia.com> Date: Thu, 25 Jun 2009 13:26:09 +0300 Subject: [PATCH 0170/1002] MAINTAINERS: Add entry for twl4030 series soc codec driver New MAINTAINERS entry for twl4030 series soc codec driver with Peter Ujfalusi as maintainer. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1ae5a81f44360..a20ac54f02501 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5523,6 +5523,13 @@ M: dsaxena@plexity.net S: Maintained F: drivers/char/hw_random/omap-rng.c +TI TWL4030 SERIES SOC CODEC DRIVER +P: Peter Ujfalusi +M: peter.ujfalusi@nokia.com +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +S: Maintained +F: sound/soc/codecs/twl4030* + TIPC NETWORK LAYER P: Per Liden M: per.liden@ericsson.com -- GitLab From 7aa5514e7170c6179272bc638a980adc1738fd29 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen <aaro.koskinen@nokia.com> Date: Mon, 22 Jun 2009 09:23:36 +0100 Subject: [PATCH 0171/1002] [ARM] 5560/1: Avoid buffer overrun in case of an invalid IRQ handle_bad_irq() expects the IRQ number to be valid (used for statistics), so it cannot be called with an illegal vector. The problem was reported by a static analysis tool. The change makes bad_irq_desc redundant, so delete it. Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/kernel/irq.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 096f600dc8d84..b7c3490eaa24a 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -98,17 +98,6 @@ int show_interrupts(struct seq_file *p, void *v) return 0; } -/* Handle bad interrupts */ -static struct irq_desc bad_irq_desc = { - .handle_irq = handle_bad_irq, - .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock), -}; - -#ifdef CONFIG_CPUMASK_OFFSTACK -/* We are not allocating bad_irq_desc.affinity or .pending_mask */ -#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK." -#endif - /* * do_IRQ handles all hardware IRQ's. Decoded IRQs should not * come via this function. Instead, they should provide their @@ -124,10 +113,13 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ - if (irq >= NR_IRQS) - handle_bad_irq(irq, &bad_irq_desc); - else + if (unlikely(irq >= NR_IRQS)) { + if (printk_ratelimit()) + printk(KERN_WARNING "Bad IRQ%u\n", irq); + ack_bad_irq(irq); + } else { generic_handle_irq(irq); + } /* AT91 specific workaround */ irq_finish(irq); @@ -165,10 +157,6 @@ void __init init_IRQ(void) for (irq = 0; irq < NR_IRQS; irq++) irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE; -#ifdef CONFIG_SMP - cpumask_setall(bad_irq_desc.affinity); - bad_irq_desc.node = smp_processor_id(); -#endif init_arch_irq(); } -- GitLab From f6430a938dc6d77e33722aaf6a58382b3423935d Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@stericsson.com> Date: Wed, 24 Jun 2009 23:38:56 +0100 Subject: [PATCH 0172/1002] [ARM] 5565/2: Use PAGE_SIZE and RO_DATA() in link script Update the link script for ARM to use PAGE_SIZE instead of hard- coded 4096. Also the old RODATA macro is deprecated for the RO_DATA(PAGE_SIZE) macro. As a consequence the PAGE_SIZE was changed from (1UL << PAGE_SHIFT) to (_AC(1,UL) << PAGE_SHIFT) because the linker does not understand the "UL" suffix to numeric constants. Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/page.h | 2 +- arch/arm/kernel/vmlinux.lds.S | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index be962c1349c4a..9c746af1bf6e1 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -12,7 +12,7 @@ /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) #ifndef __ASSEMBLY__ diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4340bf3d2c84a..69371028a2025 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -6,6 +6,7 @@ #include <asm-generic/vmlinux.lds.h> #include <asm/thread_info.h> #include <asm/memory.h> +#include <asm/page.h> OUTPUT_ARCH(arm) ENTRY(stext) @@ -63,7 +64,7 @@ SECTIONS usr/built-in.o(.init.ramfs) __initramfs_end = .; #endif - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __per_cpu_load = .; __per_cpu_start = .; *(.data.percpu.page_aligned) @@ -73,7 +74,7 @@ SECTIONS #ifndef CONFIG_XIP_KERNEL __init_begin = _stext; INIT_DATA - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_end = .; #endif } @@ -118,7 +119,7 @@ SECTIONS *(.got) /* Global offset table */ } - RODATA + RO_DATA(PAGE_SIZE) _etext = .; /* End of text and rodata section */ @@ -158,17 +159,17 @@ SECTIONS *(.data.init_task) #ifdef CONFIG_XIP_KERNEL - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_begin = .; INIT_DATA - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_end = .; #endif - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __nosave_begin = .; *(.data.nosave) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __nosave_end = .; /* -- GitLab From 14744d7da2e6ab5c6d8e82c84dc280e3c0dd8552 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch <clemens@ladisch.de> Date: Thu, 25 Jun 2009 14:28:49 +0200 Subject: [PATCH 0173/1002] sound: oxygen: make mic volume control mono The microphone input and its volume register have only one channel, so we have to make the corresponding mixer control a mono control. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/oxygen/oxygen_mixer.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 304da169bfdcb..5401c547c4e33 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -575,8 +575,10 @@ static int ac97_switch_put(struct snd_kcontrol *ctl, static int ac97_volume_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { + int stereo = (ctl->private_value >> 16) & 1; + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; + info->count = stereo ? 2 : 1; info->value.integer.min = 0; info->value.integer.max = 0x1f; return 0; @@ -587,6 +589,7 @@ static int ac97_volume_get(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; unsigned int codec = (ctl->private_value >> 24) & 1; + int stereo = (ctl->private_value >> 16) & 1; unsigned int index = ctl->private_value & 0xff; u16 reg; @@ -594,7 +597,8 @@ static int ac97_volume_get(struct snd_kcontrol *ctl, reg = oxygen_read_ac97(chip, codec, index); mutex_unlock(&chip->mutex); value->value.integer.value[0] = 31 - (reg & 0x1f); - value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); + if (stereo) + value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); return 0; } @@ -603,6 +607,7 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, { struct oxygen *chip = ctl->private_data; unsigned int codec = (ctl->private_value >> 24) & 1; + int stereo = (ctl->private_value >> 16) & 1; unsigned int index = ctl->private_value & 0xff; u16 oldreg, newreg; int change; @@ -612,8 +617,11 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, newreg = oldreg; newreg = (newreg & ~0x1f) | (31 - (value->value.integer.value[0] & 0x1f)); - newreg = (newreg & ~0x1f00) | - ((31 - (value->value.integer.value[0] & 0x1f)) << 8); + if (stereo) + newreg = (newreg & ~0x1f00) | + ((31 - (value->value.integer.value[1] & 0x1f)) << 8); + else + newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8); change = newreg != oldreg; if (change) oxygen_write_ac97(chip, codec, index, newreg); @@ -673,7 +681,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, .private_value = ((codec) << 24) | ((invert) << 16) | \ ((bitnr) << 8) | (index), \ } -#define AC97_VOLUME(xname, codec, index) { \ +#define AC97_VOLUME(xname, codec, index, stereo) { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ @@ -682,7 +690,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, .get = ac97_volume_get, \ .put = ac97_volume_put, \ .tlv = { .p = ac97_db_scale, }, \ - .private_value = ((codec) << 24) | (index), \ + .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ } static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0); @@ -882,18 +890,18 @@ static const struct { }; static const struct snd_kcontrol_new ac97_controls[] = { - AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC), + AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), - AC97_VOLUME("CD Capture Volume", 0, AC97_CD), + AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), - AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX), + AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX, 1), AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1), }; static const struct snd_kcontrol_new ac97_fp_controls[] = { - AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE), + AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE, 1), AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -- GitLab From 308ff823ebd749a94d3b6ac26b95bc0eb114c39e Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Thu, 25 Jun 2009 16:32:52 +0200 Subject: [PATCH 0174/1002] nf_conntrack: Use rcu_barrier() RCU barriers, rcu_barrier(), is inserted two places. In nf_conntrack_expect.c nf_conntrack_expect_fini() before the kmem_cache_destroy(). Firstly to make sure the callback to the nf_ct_expect_free_rcu() code is still around. Secondly because I'm unsure about the consequence of having in flight nf_ct_expect_free_rcu/kmem_cache_free() calls while doing a kmem_cache_destroy() slab destroy. And in nf_conntrack_extend.c nf_ct_extend_unregister(), inorder to wait for completion of callbacks to __nf_ct_ext_free_rcu(), which is invoked by __nf_ct_ext_add(). It might be more efficient to call rcu_barrier() in nf_conntrack_core.c nf_conntrack_cleanup_net(), but thats make it more difficult to read the code (as the callback code in located in nf_conntrack_extend.c). Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: Patrick McHardy <kaber@trash.net> --- net/netfilter/nf_conntrack_expect.c | 4 +++- net/netfilter/nf_conntrack_extend.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index afde8f991646e..2032dfe25ca85 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -617,8 +617,10 @@ int nf_conntrack_expect_init(struct net *net) void nf_conntrack_expect_fini(struct net *net) { exp_proc_remove(net); - if (net_eq(net, &init_net)) + if (net_eq(net, &init_net)) { + rcu_barrier(); /* Wait for call_rcu() before destroy */ kmem_cache_destroy(nf_ct_expect_cachep); + } nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, nf_ct_expect_hsize); } diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 4b2c769d555fc..fef95be334bd8 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -186,6 +186,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); update_alloc_size(type); mutex_unlock(&nf_ct_ext_type_mutex); - synchronize_rcu(); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); -- GitLab From e5c59547791f171b280bc4c4b2c3ff171824c1a3 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 25 Jun 2009 18:25:22 +0530 Subject: [PATCH 0175/1002] perf_counter tools: Shorten names for events Added new alias for events. On AMD box: $ ./perf stat -e l1d -e l1d-misses -e l1d-write -e l1d-prefetch -e l1d-prefetch-miss -e l1i -e l1i-misses -e l1i-prefetch -e l2 -e l2-misses -e l2-write -e dtlb -e dtlb-misses -e itlb -e itlb-misses -e bpu -e bpu-misses -- ls -lR /usr/include/ > /dev/null Before : Performance counter stats for 'ls -lR /usr/include/': 248064467 L1-data-Cache-Load-Referencees (scaled from 23.27%) 1001433 L1-data-Cache-Load-Misses (scaled from 23.34%) 153691 L1-data-Cache-Store-Referencees (scaled from 23.34%) 423248 L1-data-Cache-Prefetch-Referencees (scaled from 23.33%) 302138 L1-data-Cache-Prefetch-Misses (scaled from 23.25%) 251217546 L1-instruction-Cache-Load-Referencees (scaled from 23.25%) 5757005 L1-instruction-Cache-Load-Misses (scaled from 23.23%) 93435 L1-instruction-Cache-Prefetch-Referencees (scaled from 23.24%) 6496073 L2-Cache-Load-Referencees (scaled from 23.32%) 609485 L2-Cache-Load-Misses (scaled from 23.45%) 6876991 L2-Cache-Store-Referencees (scaled from 23.71%) 248922840 Data-TLB-Cache-Load-Referencees (scaled from 23.94%) 5828386 Data-TLB-Cache-Load-Misses (scaled from 24.17%) 257613506 Instruction-TLB-Cache-Load-Referencees (scaled from 24.20%) 6833 Instruction-TLB-Cache-Load-Misses (scaled from 23.88%) 109043606 Branch-Cache-Load-Referencees (scaled from 23.64%) 5552296 Branch-Cache-Load-Misses (scaled from 23.42%) 0.413702461 seconds time elapsed. After : Peformance counter stats for 'ls -lR /usr/include/': 266590464 L1-d$-loads (scaled from 23.03%) 1222273 L1-d$-load-misses (scaled from 23.58%) 146204 L1-d$-stores (scaled from 23.83%) 406344 L1-d$-prefetches (scaled from 24.09%) 283748 L1-d$-prefetch-misses (scaled from 24.10%) 249650965 L1-i$-loads (scaled from 23.80%) 3353961 L1-i$-load-misses (scaled from 23.82%) 104599 L1-i$-prefetches (scaled from 23.68%) 4836405 LLC-loads (scaled from 23.67%) 498214 LLC-load-misses (scaled from 23.66%) 4953994 LLC-stores (scaled from 23.64%) 243354097 dTLB-loads (scaled from 23.77%) 6468584 dTLB-load-misses (scaled from 23.74%) 249719549 iTLB-loads (scaled from 23.25%) 5060 iTLB-load-misses (scaled from 23.00%) 112343016 branch-loads (scaled from 22.76%) 5528876 branch-load-misses (scaled from 22.54%) 0.427154051 seconds time elapsed. Reported-by : Ingo Molnar <mingo@elte.hu> Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1245934522.5308.39.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 45 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 7939a21130d2b..430f06083201a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -71,23 +71,23 @@ static char *sw_event_names[] = { #define MAX_ALIASES 8 static char *hw_cache[][MAX_ALIASES] = { - { "L1-data", "l1-d", "l1d" }, - { "L1-instruction", "l1-i", "l1i" }, - { "L2", "l2" }, - { "Data-TLB", "dtlb", "d-tlb" }, - { "Instruction-TLB", "itlb", "i-tlb" }, - { "Branch", "bpu" , "btb", "bpc" }, + { "L1-d$", "l1-d", "L1-data", }, + { "L1-i$", "l1-i", "L1-instruction", }, + { "LLC", "L2" }, + { "dTLB", "d-tlb", "Data-TLB", }, + { "iTLB", "i-tlb", "Instruction-TLB", }, + { "branch", "branches", "bpu", "btb", "bpc", }, }; static char *hw_cache_op[][MAX_ALIASES] = { - { "Load", "read" }, - { "Store", "write" }, - { "Prefetch", "speculative-read", "speculative-load" }, + { "load", "loads", "read", }, + { "store", "stores", "write", }, + { "prefetch", "prefetches", "speculative-read", "speculative-load", }, }; static char *hw_cache_result[][MAX_ALIASES] = { - { "Reference", "ops", "access" }, - { "Miss" }, + { "refs", "Reference", "ops", "access", }, + { "misses", "miss", }, }; #define C(x) PERF_COUNT_HW_CACHE_##x @@ -118,6 +118,22 @@ static int is_cache_op_valid(u8 cache_type, u8 cache_op) return 0; /* invalid */ } +static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) +{ + static char name[50]; + + if (cache_result) { + sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], + hw_cache_op[cache_op][0], + hw_cache_result[cache_result][0]); + } else { + sprintf(name, "%s-%s", hw_cache[cache_type][0], + hw_cache_op[cache_op][1]); + } + + return name; +} + char *event_name(int counter) { u64 config = attrs[counter].config; @@ -137,7 +153,6 @@ char *event_name(int counter) case PERF_TYPE_HW_CACHE: { u8 cache_type, cache_op, cache_result; - static char name[100]; cache_type = (config >> 0) & 0xff; if (cache_type > PERF_COUNT_HW_CACHE_MAX) @@ -153,12 +168,8 @@ char *event_name(int counter) if (!is_cache_op_valid(cache_type, cache_op)) return "invalid-cache"; - sprintf(name, "%s-Cache-%s-%ses", - hw_cache[cache_type][0], - hw_cache_op[cache_op][0], - hw_cache_result[cache_result][0]); - return name; + return event_cache_name(cache_type, cache_op, cache_result); } case PERF_TYPE_SOFTWARE: -- GitLab From e08afeb7e69f45e4ab9fbb8530fe433484b96606 Mon Sep 17 00:00:00 2001 From: Brian King <brking@linux.vnet.ibm.com> Date: Tue, 23 Jun 2009 17:14:01 -0500 Subject: [PATCH 0176/1002] [SCSI] ibmvscsi: Fix module load hang Fixes a regression seen in the ibmvscsi driver when using the VSCSI server in SLES 9 and SLES 10. The VSCSI server in these releases has a bug in it in which it does not send responses to unknown MADs. Check the OS Type field in the adapter info response and do not send these unsupported commands when talking to an older server. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/ibmvscsi/ibmvscsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 869a11bdccbdf..9928704e235f4 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) MAX_INDIRECT_BUFS); hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; } + + if (hostdata->madapter_info.os_type == 3) { + enable_fast_fail(hostdata); + return; + } } - enable_fast_fail(hostdata); + send_srp_login(hostdata); } /** -- GitLab From 87a2d34b0372dcf6bc4caf4d97a7889f5e62a1af Mon Sep 17 00:00:00 2001 From: Roel Kluin <roel.kluin@gmail.com> Date: Tue, 23 Jun 2009 01:06:40 +0200 Subject: [PATCH 0177/1002] [SCSI] fnic: remove redundant BUG_ONs and fix checks on unsigned The shost sg tablesize is set to FNIC_MAX_SG_DESC_CNT and fnic uses scsi_dma_map, so both BUG_ONs can be removed. scsi_dma_map may return -ENOMEM, sg_count should be int to catch that. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/fnic/fnic_scsi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index eabf365028568..bfc996971b814 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, struct vnic_wq_copy *wq, struct fnic_io_req *io_req, struct scsi_cmnd *sc, - u32 sg_count) + int sg_count) { struct scatterlist *sg; struct fc_rport *rport = starget_to_rport(scsi_target(sc->device)); @@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic, char msg[2]; if (sg_count) { - BUG_ON(sg_count < 0); - BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT); - /* For each SGE, create a device desc entry */ desc = io_req->sgl_list; for_each_sg(scsi_sglist(sc), sg, sg_count, i) { @@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) struct fnic *fnic; struct vnic_wq_copy *wq; int ret; - u32 sg_count; + int sg_count; unsigned long flags; unsigned long ptr; -- GitLab From e3f47cc74bddea8121560026185ede4770170043 Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar <abjoglek@cisco.com> Date: Wed, 24 Jun 2009 07:42:25 -0700 Subject: [PATCH 0178/1002] [SCSI] fnic: use DMA_BIT_MASK(nn) instead of deprecated DMA_nnBIT_MASK Robert Love reported warning while building fnic_main.c: drivers/scsi/fnic/fnic_main.c:478: warning: `DMA_nnBIT_MASK' is deprecated. Replaced use of DMA_nnBIT_MASK by DMA_BIT_MASK(nn) Signed-off-by: Abhijeet Joglekar <abjoglek@cisco.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/fnic/fnic_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index a84072865fc26..2c266c01dc5ad 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev, * limitation for the device. Try 40-bit first, and * fail to 32-bit. */ - err = pci_set_dma_mask(pdev, DMA_40BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); if (err) { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { shost_printk(KERN_ERR, fnic->lport->host, "No usable DMA configuration " "aborting\n"); goto err_out_release_regions; } - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { shost_printk(KERN_ERR, fnic->lport->host, "Unable to obtain 32-bit DMA " @@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev, goto err_out_release_regions; } } else { - err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40)); if (err) { shost_printk(KERN_ERR, fnic->lport->host, "Unable to obtain 40-bit DMA " -- GitLab From d3a263a8168f78874254ea9da9595cfb0f3e96d7 Mon Sep 17 00:00:00 2001 From: James Bottomley <James.Bottomley@HansenPartnership.com> Date: Wed, 24 Jun 2009 19:55:22 +0000 Subject: [PATCH 0179/1002] [SCSI] zalon: fix oops on attach failure I recently discovered on my zalon that if the attachment fails because of a bus misconfiguration (I scrapped my HVD array, so the card is now unterminated) then the system oopses. The reason is that if ncr_attach() returns NULL (signalling failure) that NULL is passed by the goto failed straight into ncr_detach() which oopses. The fix is just to return -ENODEV in this case. Cc: Stable Tree <stable@kernel.org> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/zalon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 97f3158fa7b54..27e84e4b1fa98 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev) host = ncr_attach(&zalon7xx_template, unit, &device); if (!host) - goto fail; + return -ENODEV; if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", -- GitLab From 6fdc03709433ccc2005f0f593ae9d9dd04f7b485 Mon Sep 17 00:00:00 2001 From: Stefan Richter <stefanr@s5r6.in-berlin.de> Date: Sat, 20 Jun 2009 13:23:59 +0200 Subject: [PATCH 0180/1002] firewire: core: do not DMA-map stack addresses The DMA mapping API cannot map on-stack addresses, as explained in Documentation/DMA-mapping.txt. Convert the two cases of on-stack packet payload buffers in firewire-core (payload of lock requests in the bus manager work and in iso resource management) to slab-allocated memory. There are a number on-stack buffers for quadlet write or quadlet read requests in firewire-core and firewire-sbp2. These are harmless; they are copied to/ from card driver internal DMA buffers since quadlet payloads are inlined with packet headers. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/firewire/core-card.c | 14 +++++++------- drivers/firewire/core-cdev.c | 4 +++- drivers/firewire/core-iso.c | 24 +++++++++++++----------- drivers/firewire/core.h | 3 ++- include/linux/firewire.h | 1 + 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81bb9..f74edae5cb4cf 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) { int channel, bandwidth = 0; - fw_iso_resource_manage(card, generation, 1ULL << 31, - &channel, &bandwidth, true); + fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, + &bandwidth, true, card->bm_transaction_data); if (channel == 31) { card->broadcast_channel_allocated = true; device_for_each_child(card->device, (void *)(long)generation, @@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) bool do_reset = false; bool root_device_is_running; bool root_device_is_cmc; - __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); @@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) goto pick_me; } - lock_data[0] = cpu_to_be32(0x3f); - lock_data[1] = cpu_to_be32(local_id); + card->bm_transaction_data[0] = cpu_to_be32(0x3f); + card->bm_transaction_data[1] = cpu_to_be32(local_id); spin_unlock_irqrestore(&card->lock, flags); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - lock_data, sizeof(lock_data)); + card->bm_transaction_data, + sizeof(card->bm_transaction_data)); if (rcode == RCODE_GENERATION) /* Another bus reset, BM work has been rescheduled. */ goto out; if (rcode == RCODE_COMPLETE && - lock_data[0] != cpu_to_be32(0x3f)) { + card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { /* Somebody else is BM. Only act as IRM. */ if (local_id == irm_id) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0f1..ced186d7e9a9d 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -125,6 +125,7 @@ struct iso_resource { int generation; u64 channels; s32 bandwidth; + __be32 transaction_data[2]; struct iso_resource_event *e_alloc, *e_dealloc; }; @@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) r->channels, &channel, &bandwidth, todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC || - todo == ISO_RES_ALLOC_ONCE); + todo == ISO_RES_ALLOC_ONCE, + r->transaction_data); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38d6..110e731f55741 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); */ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, - int bandwidth, bool allocate) + int bandwidth, bool allocate, __be32 data[2]) { - __be32 data[2]; int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; /* @@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, } static int manage_channel(struct fw_card *card, int irm_id, int generation, - u32 channels_mask, u64 offset, bool allocate) + u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) { - __be32 data[2], c, all, old; + __be32 c, all, old; int i, retry = 5; old = all = allocate ? cpu_to_be32(~0) : 0; @@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, } static void deallocate_channel(struct fw_card *card, int irm_id, - int generation, int channel) + int generation, int channel, __be32 buffer[2]) { u32 mask; u64 offset; @@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; - manage_channel(card, irm_id, generation, mask, offset, false); + manage_channel(card, irm_id, generation, mask, offset, false, buffer); } /** @@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, */ void fw_iso_resource_manage(struct fw_card *card, int generation, u64 channels_mask, int *channel, int *bandwidth, - bool allocate) + bool allocate, __be32 buffer[2]) { u32 channels_hi = channels_mask; /* channels 31...0 */ u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ @@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (channels_hi) c = manage_channel(card, irm_id, generation, channels_hi, - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, + allocate, buffer); if (channels_lo && c < 0) { c = manage_channel(card, irm_id, generation, channels_lo, - CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); + CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, + allocate, buffer); if (c >= 0) c += 32; } @@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (*bandwidth == 0) return; - ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, + allocate, buffer); if (ret < 0) *bandwidth = 0; if (allocate && ret < 0 && c >= 0) { - deallocate_channel(card, irm_id, generation, c); + deallocate_channel(card, irm_id, generation, c, buffer); *channel = ret; } } diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e30..6052816be353e 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); void fw_iso_resource_manage(struct fw_card *card, int generation, - u64 channels_mask, int *channel, int *bandwidth, bool allocate); + u64 channels_mask, int *channel, int *bandwidth, + bool allocate, __be32 buffer[2]); /* -topology */ diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 9823946adbc51..192d1e43c43c3 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -127,6 +127,7 @@ struct fw_card { struct delayed_work work; int bm_retries; int bm_generation; + __be32 bm_transaction_data[2]; bool broadcast_channel_allocated; u32 broadcast_channel; -- GitLab From 47749b14e55cd167632f9a27a4fc439e591e5268 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Thu, 25 Jun 2009 08:27:14 +0200 Subject: [PATCH 0181/1002] i2c: fix build bug in i2c-designware.c This build error triggers on x86: drivers/built-in.o: In function `i2c_dw_init': i2c-designware.c:(.text+0x4e37ca): undefined reference to `clk_get_rate' drivers/built-in.o: In function `dw_i2c_probe': i2c-designware.c:(.devinit.text+0x51f5e): undefined reference to `clk_get' i2c-designware.c:(.devinit.text+0x51f76): undefined reference to `clk_enable' i2c-designware.c:(.devinit.text+0x520ff): undefined reference to `clk_disable' i2c-designware.c:(.devinit.text+0x52108): undefined reference to `clk_put' Because this new driver uses the clk_*() facilities which is an ARM-only thing currently. Signed-off-by: Ingo Molnar <mingo@elte.hu> Acked-by: Baruch Siach <baruch@tkos.co.il> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/i2c/busses/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index aa87b6a3bbef0..8206442fbabd8 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -328,6 +328,7 @@ config I2C_DAVINCI config I2C_DESIGNWARE tristate "Synopsys DesignWare" + depends on HAVE_CLK help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. -- GitLab From ab420e6d9c2511b862d753b70efb4e979faa0714 Mon Sep 17 00:00:00 2001 From: Paul Menage <menage@google.com> Date: Thu, 25 Jun 2009 00:17:15 -0700 Subject: [PATCH 0182/1002] UML: Fix some apparent bitrot UML: Fix some apparent bitrot - migration of net_device methods into net_device_ops - dma_sync_single() changes Signed-off-by: Paul Menage <menage@google.com> Acked-by: Amerigo Wang <xiyou.wangcong@gmail.com> -- This version is split from my earlier patch, including just the portions that ar required for Linus' tree. Fixes the following compile errors: include/linux/dma-mapping.h:113: error: redefinition of 'dma_sync_single' arch/um/include/asm/dma-mapping.h:84: error: previous definition of 'dma_sync_single' was here include/linux/dma-mapping.h: In function 'dma_sync_single': include/linux/dma-mapping.h:117: error: implicit declaration of function 'dma_sync_single_for_cpu' include/linux/dma-mapping.h: At top level: include/linux/dma-mapping.h:120: error: redefinition of 'dma_sync_sg' arch/um/include/asm/dma-mapping.h:91: error: previous definition of 'dma_sync_sg' was here include/linux/dma-mapping.h: In function 'dma_sync_sg': include/linux/dma-mapping.h:124: error: implicit declaration of function 'dma_sync_sg_for_cpu' arch/um/drivers/slirp_kern.c: In function 'slirp_init': arch/um/drivers/slirp_kern.c:35: error: 'struct net_device' has no member named 'init' Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/um/drivers/slip_kern.c | 1 - arch/um/drivers/slirp_kern.c | 1 - arch/um/include/asm/dma-mapping.h | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 5ec17563142e2..dd2aadc14af0a 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c @@ -30,7 +30,6 @@ static void slip_init(struct net_device *dev, void *data) slip_proto_init(&spri->slip); - dev->init = NULL; dev->hard_header_len = 0; dev->header_ops = NULL; dev->addr_len = 0; diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index f15a6e7654f36..e376284f0fb7f 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -32,7 +32,6 @@ void slirp_init(struct net_device *dev, void *data) slip_proto_init(&spri->slip); - dev->init = NULL; dev->hard_header_len = 0; dev->header_ops = NULL; dev->addr_len = 0; diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h index 90fc708b320e4..378de4bbf49ff 100644 --- a/arch/um/include/asm/dma-mapping.h +++ b/arch/um/include/asm/dma-mapping.h @@ -79,14 +79,14 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, } static inline void -dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { BUG(); } static inline void -dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { BUG(); -- GitLab From 9d73777e500929b71dcfed16eec05f6760e345a6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <peterz@infradead.org> Date: Thu, 25 Jun 2009 11:58:55 +0200 Subject: [PATCH 0183/1002] clarify get_user_pages() prototype Currently the 4th parameter of get_user_pages() is called len, but its in pages, not bytes. Rename the thing to nr_pages to avoid future confusion. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/mm.h | 2 +- mm/memory.c | 26 ++++++++++++-------------- mm/nommu.c | 12 +++++------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index d006e93d5c93c..ba3a7cb1eaa0d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -826,7 +826,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - unsigned long start, int len, int write, int force, + unsigned long start, int nr_pages, int write, int force, struct page **pages, struct vm_area_struct **vmas); int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages); diff --git a/mm/memory.c b/mm/memory.c index f46ac18ba2311..65216194eb8da 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1207,8 +1207,8 @@ static inline int use_zero_page(struct vm_area_struct *vma) int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - unsigned long start, int len, int flags, - struct page **pages, struct vm_area_struct **vmas) + unsigned long start, int nr_pages, int flags, + struct page **pages, struct vm_area_struct **vmas) { int i; unsigned int vm_flags = 0; @@ -1217,7 +1217,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS); int ignore_sigkill = !!(flags & GUP_FLAGS_IGNORE_SIGKILL); - if (len <= 0) + if (nr_pages <= 0) return 0; /* * Require read or write permissions. @@ -1269,7 +1269,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, vmas[i] = gate_vma; i++; start += PAGE_SIZE; - len--; + nr_pages--; continue; } @@ -1280,7 +1280,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (is_vm_hugetlb_page(vma)) { i = follow_hugetlb_page(mm, vma, pages, vmas, - &start, &len, i, write); + &start, &nr_pages, i, write); continue; } @@ -1357,9 +1357,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, vmas[i] = vma; i++; start += PAGE_SIZE; - len--; - } while (len && start < vma->vm_end); - } while (len); + nr_pages--; + } while (nr_pages && start < vma->vm_end); + } while (nr_pages); return i; } @@ -1368,7 +1368,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * @tsk: task_struct of target task * @mm: mm_struct of target mm * @start: starting user address - * @len: number of pages from start to pin + * @nr_pages: number of pages from start to pin * @write: whether pages will be written to by the caller * @force: whether to force write access even if user mapping is * readonly. This will result in the page being COWed even @@ -1380,7 +1380,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * Or NULL if the caller does not require them. * * Returns number of pages pinned. This may be fewer than the number - * requested. If len is 0 or negative, returns 0. If no pages + * requested. If nr_pages is 0 or negative, returns 0. If no pages * were pinned, returns -errno. Each page returned must be released * with a put_page() call when it is finished with. vmas will only * remain valid while mmap_sem is held. @@ -1414,7 +1414,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * See also get_user_pages_fast, for performance critical applications. */ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - unsigned long start, int len, int write, int force, + unsigned long start, int nr_pages, int write, int force, struct page **pages, struct vm_area_struct **vmas) { int flags = 0; @@ -1424,9 +1424,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (force) flags |= GUP_FLAGS_FORCE; - return __get_user_pages(tsk, mm, - start, len, flags, - pages, vmas); + return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); } EXPORT_SYMBOL(get_user_pages); diff --git a/mm/nommu.c b/mm/nommu.c index 2fd2ad5da98e5..bf0cc762a7d20 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -173,8 +173,8 @@ unsigned int kobjsize(const void *objp) } int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - unsigned long start, int len, int flags, - struct page **pages, struct vm_area_struct **vmas) + unsigned long start, int nr_pages, int flags, + struct page **pages, struct vm_area_struct **vmas) { struct vm_area_struct *vma; unsigned long vm_flags; @@ -189,7 +189,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); - for (i = 0; i < len; i++) { + for (i = 0; i < nr_pages; i++) { vma = find_vma(mm, start); if (!vma) goto finish_or_fault; @@ -224,7 +224,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * - don't permit access to VMAs that don't support it, such as I/O mappings */ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - unsigned long start, int len, int write, int force, + unsigned long start, int nr_pages, int write, int force, struct page **pages, struct vm_area_struct **vmas) { int flags = 0; @@ -234,9 +234,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (force) flags |= GUP_FLAGS_FORCE; - return __get_user_pages(tsk, mm, - start, len, flags, - pages, vmas); + return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); } EXPORT_SYMBOL(get_user_pages); -- GitLab From 42dd2aa6496a2e87e496aac5494d2e1d6096c85b Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Thu, 25 Jun 2009 14:41:24 +0100 Subject: [PATCH 0184/1002] acm: Return ENODEV instead of EINVAL when trying to open ACM device. This is required, otherwise a user will get a EINVAL while opening a non-existing device, instead of ENODEV. This is what I get with this patch applied now instead of an "Invalid argument". cascardo@vespa:~$ cat /dev/ttyACM0 cat: /dev/ttyACM0: No such device cascardo@vespa:~$ Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 38bfdb0f66605..02eb60bb67956 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -550,7 +550,7 @@ static void acm_waker(struct work_struct *waker) static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; - int rv = -EINVAL; + int rv = -ENODEV; int i; dbg("Entering acm_tty_open."); -- GitLab From 922b13565b6a826a925f9f91f053dc9cb0d6210e Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Thu, 25 Jun 2009 14:41:30 +0100 Subject: [PATCH 0185/1002] acm: Fix oops when closing ACM tty device right after open has failed. This commit 10077d4a6674f535abdbe25cdecb1202af7948f1 has stopped checking if there was a valid acm device associated to the tty, which is not true right after open fails and tty subsystem tries to close the device. As an example, open fails with a non-existing device, when probe has never been called, because the device has never been plugged. This is common in systems with static modules and no udev. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 02eb60bb67956..3f1045993474c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -677,7 +677,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) /* Perform the closing process and see if we need to do the hardware shutdown */ - if (tty_port_close_start(&acm->port, tty, filp) == 0) + if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0) return; acm_port_down(acm, 0); tty_port_close_end(&acm->port, tty); -- GitLab From f4fa446883959c1c5f314a043e750dbfe3728c55 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Thu, 25 Jun 2009 14:41:37 +0100 Subject: [PATCH 0186/1002] usb_serial: Fix oops when unexisting usb serial device is opened. This commit 335f8514f200e63d689113d29cb7253a5c282967 has stopped properly checking if there is any usb serial associated with the tty in the close function. It happens the close function is called by releasing the terminal right after opening the device fails. As an example, open fails with a non-existing device, when probe has never been called, because the device has never been plugged. This is common in systems with static modules and no udev. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d595aa5586a73..a84216464ca01 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -333,6 +333,9 @@ static void serial_close(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; + if (!port) + return; + dbg("%s - port %d", __func__, port->number); -- GitLab From 0f3bc09ee1b7fcadd5bfdc5ed2e1643f658fe23d Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman <sjayaraman@suse.de> Date: Thu, 25 Jun 2009 18:12:34 +0530 Subject: [PATCH 0187/1002] cifs: Fix incorrect return code being printed in cFYI messages FreeXid() along with freeing Xid does add a cifsFYI debug message that prints rc (return code) as well. In some code paths where we set/return error code after calling FreeXid(), incorrect error code is being printed when cifsFYI is enabled. This could be misleading in few cases. For eg. In cifs_open() if cifs_fill_filedata() returns a valid pointer to cifsFileInfo, FreeXid() prints rc=-13 whereas 0 is actually being returned. Fix this by setting rc before calling FreeXid(). Basically convert FreeXid(xid); rc = -ERR; return -ERR; => FreeXid(xid); return rc; [Note that Christoph would like to replace the GetXid/FreeXid calls, which are primarily used for debugging. This seems like a good longer term goal, but although there is an alternative tracing facility, there are no examples yet available that I know of that we can use (yet) to convert this cifs function entry/exit logging, and for creating an identifier that we can use to correlate all dmesg log entries for a particular vfs operation (ie identify all log entries for a particular vfs request to cifs: e.g. a particular close or read or write or byte range lock call ... and just using the thread id is harder). Eventually when a replacement for this is available (e.g. when NFS switches over and various samples to look at in other file systems) we can remove the GetXid/FreeXid macro but in the meantime multiple people use this run time configurable logging all the time for debugging, and Suresh's patch fixes a problem which made it harder to notice some low memory problems in the log so it is worthwhile to fix this problem until a better logging approach is able to be used] Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/dir.c | 6 ++++-- fs/cifs/file.c | 24 ++++++++++++++++-------- fs/cifs/inode.c | 15 ++++++++++----- fs/cifs/link.c | 3 ++- fs/cifs/xattr.c | 12 ++++++++---- 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 3758965d73d56..7dc6b74f9deff 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -307,8 +307,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } if (oplockEnabled) @@ -540,8 +541,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (buf == NULL) { kfree(full_path); + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } rc = CIFSSMBOpen(xid, pTcon, full_path, diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06866841b97f1..ebdbe62a829cf 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -300,14 +300,16 @@ int cifs_open(struct inode *inode, struct file *file) pCifsInode = CIFS_I(file->f_path.dentry->d_inode); pCifsFile = cifs_fill_filedata(file); if (pCifsFile) { + rc = 0; FreeXid(xid); - return 0; + return rc; } full_path = build_path_from_dentry(file->f_path.dentry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", @@ -494,8 +496,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush) mutex_unlock(&pCifsFile->fh_mutex); if (!pCifsFile->invalidHandle) { mutex_lock(&pCifsFile->fh_mutex); + rc = 0; FreeXid(xid); - return 0; + return rc; } if (file->f_path.dentry == NULL) { @@ -845,8 +848,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) tcon = cifs_sb->tcon; if (file->private_data == NULL) { + rc = -EBADF; FreeXid(xid); - return -EBADF; + return rc; } netfid = ((struct cifsFileInfo *)file->private_data)->netfid; @@ -1805,8 +1809,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, pTcon = cifs_sb->tcon; if (file->private_data == NULL) { + rc = -EBADF; FreeXid(xid); - return -EBADF; + return rc; } open_file = (struct cifsFileInfo *)file->private_data; @@ -1885,8 +1890,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, pTcon = cifs_sb->tcon; if (file->private_data == NULL) { + rc = -EBADF; FreeXid(xid); - return -EBADF; + return rc; } open_file = (struct cifsFileInfo *)file->private_data; @@ -2019,8 +2025,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, xid = GetXid(); if (file->private_data == NULL) { + rc = -EBADF; FreeXid(xid); - return -EBADF; + return rc; } open_file = (struct cifsFileInfo *)file->private_data; cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); @@ -2185,8 +2192,9 @@ static int cifs_readpage(struct file *file, struct page *page) xid = GetXid(); if (file->private_data == NULL) { + rc = -EBADF; FreeXid(xid); - return -EBADF; + return rc; } cFYI(1, ("readpage %p at offset %d 0x%x\n", diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fad882b075ba5..155c9e785d0c6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -988,8 +988,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) * sb->s_vfs_rename_mutex here */ full_path = build_path_from_dentry(dentry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } if ((tcon->ses->capabilities & CAP_UNIX) && @@ -1118,8 +1119,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } if ((pTcon->ses->capabilities & CAP_UNIX) && @@ -1303,8 +1305,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, @@ -1508,8 +1511,9 @@ int cifs_revalidate(struct dentry *direntry) since that would deadlock */ full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " "jiffies %ld", full_path, direntry->d_inode, @@ -1911,8 +1915,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } /* diff --git a/fs/cifs/link.c b/fs/cifs/link.c index cd83c53fcbb54..fc1e0487eaee3 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -172,8 +172,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } cFYI(1, ("Full path: %s", full_path)); diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index e9527eedc6396..a75afa3dd9e18 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -64,8 +64,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } if (ea_name == NULL) { cFYI(1, ("Null xattr names not supported")); @@ -118,8 +119,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -225,8 +227,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ @@ -351,8 +354,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) full_path = build_path_from_dentry(direntry); if (full_path == NULL) { + rc = -ENOMEM; FreeXid(xid); - return -ENOMEM; + return rc; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ -- GitLab From dfc2f91ac29f5ef50e74bf15a1a6b6aa6b952e62 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Fri, 26 Jun 2009 04:31:57 +0900 Subject: [PATCH 0188/1002] nommu: provide follow_pfn(). With the introduction of follow_pfn() as an exported symbol, modules have begun making use of it. Unfortunately this was not reflected on nommu at the time, so the in-tree users have subsequently all blown up with link errors there. This provides a simple follow_pfn() that just returns addr >> PAGE_SHIFT, which will do the right thing on nommu. There is no need to do range checking within the vma, as the find_vma() case will already take care of this. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- mm/nommu.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mm/nommu.c b/mm/nommu.c index 2fd2ad5da98e5..598bc871487a8 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -240,6 +240,27 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, } EXPORT_SYMBOL(get_user_pages); +/** + * follow_pfn - look up PFN at a user virtual address + * @vma: memory mapping + * @address: user virtual address + * @pfn: location to store found PFN + * + * Only IO mappings and raw PFN mappings are allowed. + * + * Returns zero and the pfn at @pfn on success, -ve otherwise. + */ +int follow_pfn(struct vm_area_struct *vma, unsigned long address, + unsigned long *pfn) +{ + if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) + return -EINVAL; + + *pfn = address >> PAGE_SHIFT; + return 0; +} +EXPORT_SYMBOL(follow_pfn); + DEFINE_RWLOCK(vmlist_lock); struct vm_struct *vmlist; -- GitLab From 7c6a1c65bbd3be688e581511f45818663efc1877 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Thu, 25 Jun 2009 17:05:54 +0200 Subject: [PATCH 0189/1002] perf_counter tools: Rework the file format Create a structured file format that includes the full perf_counter_attr and all its relevant counter IDs so that the reporting program has full information. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 3 +- tools/perf/builtin-record.c | 100 +++++++++----- tools/perf/builtin-report.c | 37 ++++-- tools/perf/perf.h | 8 +- tools/perf/util/header.c | 242 ++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 37 ++++++ tools/perf/util/string.h | 2 +- tools/perf/util/symbol.h | 2 +- tools/perf/{ => util}/types.h | 0 9 files changed, 377 insertions(+), 54 deletions(-) create mode 100644 tools/perf/util/header.c create mode 100644 tools/perf/util/header.h rename tools/perf/{ => util}/types.h (100%) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 36d7eef499135..d3887ed51a640 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -290,7 +290,7 @@ LIB_FILE=libperf.a LIB_H += ../../include/linux/perf_counter.h LIB_H += perf.h -LIB_H += types.h +LIB_H += util/types.h LIB_H += util/list.h LIB_H += util/rbtree.h LIB_H += util/levenshtein.h @@ -328,6 +328,7 @@ LIB_OBJS += util/sigchain.o LIB_OBJS += util/symbol.o LIB_OBJS += util/color.o LIB_OBJS += util/pager.o +LIB_OBJS += util/header.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9b899ba1b4108..f4f0240d2302a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -14,6 +14,8 @@ #include "util/parse-events.h" #include "util/string.h" +#include "util/header.h" + #include <unistd.h> #include <sched.h> @@ -52,7 +54,8 @@ static int nr_poll; static int nr_cpu; static int file_new = 1; -static struct perf_file_header file_header; + +struct perf_header *header; struct mmap_event { struct perf_event_header header; @@ -328,7 +331,7 @@ static void pid_synthesize_mmap_samples(pid_t pid) fclose(fp); } -static void synthesize_samples(void) +static void synthesize_all(void) { DIR *proc; struct dirent dirent, *next; @@ -352,10 +355,35 @@ static void synthesize_samples(void) static int group_fd; +static struct perf_header_attr *get_header_attr(struct perf_counter_attr *a, int nr) +{ + struct perf_header_attr *h_attr; + + if (nr < header->attrs) { + h_attr = header->attr[nr]; + } else { + h_attr = perf_header_attr__new(a); + perf_header__add_attr(header, h_attr); + } + + return h_attr; +} + static void create_counter(int counter, int cpu, pid_t pid) { struct perf_counter_attr *attr = attrs + counter; - int track = 1; + struct perf_header_attr *h_attr; + int track = !counter; /* only the first counter needs these */ + struct { + u64 count; + u64 time_enabled; + u64 time_running; + u64 id; + } read_data; + + attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | + PERF_FORMAT_TOTAL_TIME_RUNNING | + PERF_FORMAT_ID; attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; @@ -368,22 +396,11 @@ static void create_counter(int counter, int cpu, pid_t pid) if (call_graph) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; - if (file_new) { - file_header.sample_type = attr->sample_type; - } else { - if (file_header.sample_type != attr->sample_type) { - fprintf(stderr, "incompatible append\n"); - exit(-1); - } - } - attr->mmap = track; attr->comm = track; attr->inherit = (cpu < 0) && inherit; attr->disabled = 1; - track = 0; /* only the first counter needs these */ - try_again: fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); @@ -414,6 +431,19 @@ static void create_counter(int counter, int cpu, pid_t pid) exit(-1); } + h_attr = get_header_attr(attr, counter); + + if (!file_new) { + if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { + fprintf(stderr, "incompatible append\n"); + exit(-1); + } + } + + read(fd[nr_cpu][counter], &read_data, sizeof(read_data)); + + perf_header_attr__add_id(h_attr, read_data.id); + assert(fd[nr_cpu][counter] >= 0); fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); @@ -444,11 +474,6 @@ static void open_counters(int cpu, pid_t pid) { int counter; - if (pid > 0) { - pid_synthesize_comm_event(pid, 0); - pid_synthesize_mmap_samples(pid); - } - group_fd = -1; for (counter = 0; counter < nr_counters; counter++) create_counter(counter, cpu, pid); @@ -458,17 +483,16 @@ static void open_counters(int cpu, pid_t pid) static void atexit_header(void) { - file_header.data_size += bytes_written; + header->data_size += bytes_written; - if (pwrite(output, &file_header, sizeof(file_header), 0) == -1) - perror("failed to write on file headers"); + perf_header__write(header, output); } static int __cmd_record(int argc, const char **argv) { int i, counter; struct stat st; - pid_t pid; + pid_t pid = 0; int flags; int ret; @@ -499,22 +523,31 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - if (!file_new) { - if (read(output, &file_header, sizeof(file_header)) == -1) { - perror("failed to read file headers"); - exit(-1); - } - - lseek(output, file_header.data_size, SEEK_CUR); - } + if (!file_new) + header = perf_header__read(output); + else + header = perf_header__new(); atexit(atexit_header); if (!system_wide) { - open_counters(-1, target_pid != -1 ? target_pid : getpid()); + pid = target_pid; + if (pid == -1) + pid = getpid(); + + open_counters(-1, pid); } else for (i = 0; i < nr_cpus; i++) open_counters(i, target_pid); + if (file_new) + perf_header__write(header, output); + + if (!system_wide) { + pid_synthesize_comm_event(pid, 0); + pid_synthesize_mmap_samples(pid); + } else + synthesize_all(); + if (target_pid == -1 && argc) { pid = fork(); if (pid < 0) @@ -538,9 +571,6 @@ static int __cmd_record(int argc, const char **argv) } } - if (system_wide) - synthesize_samples(); - while (!done) { int hits = samples; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b4e76f75ba87f..e575f30397669 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -17,6 +17,7 @@ #include "util/string.h" #include "perf.h" +#include "util/header.h" #include "util/parse-options.h" #include "util/parse-events.h" @@ -1385,13 +1386,27 @@ process_event(event_t *event, unsigned long offset, unsigned long head) return 0; } -static struct perf_file_header file_header; +static struct perf_header *header; + +static int perf_header__has_sample(u64 sample_mask) +{ + int i; + + for (i = 0; i < header->attrs; i++) { + struct perf_header_attr *attr = header->attr[i]; + + if (!(attr->attr.sample_type & sample_mask)) + return 0; + } + + return 1; +} static int __cmd_report(void) { int ret, rc = EXIT_FAILURE; unsigned long offset = 0; - unsigned long head = sizeof(file_header); + unsigned long head, shift; struct stat stat; event_t *event; uint32_t size; @@ -1419,13 +1434,11 @@ static int __cmd_report(void) exit(0); } - if (read(input, &file_header, sizeof(file_header)) == -1) { - perror("failed to read file headers"); - exit(-1); - } + header = perf_header__read(input); + head = header->data_offset; if (sort__has_parent && - !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) { + !perf_header__has_sample(PERF_SAMPLE_CALLCHAIN)) { fprintf(stderr, "selected --sort parent, but no callchain data\n"); exit(-1); } @@ -1445,6 +1458,11 @@ static int __cmd_report(void) cwd = NULL; cwdlen = 0; } + + shift = page_size * (head / page_size); + offset += shift; + head -= shift; + remap: buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, MAP_SHARED, input, offset); @@ -1461,9 +1479,10 @@ static int __cmd_report(void) size = 8; if (head + event->header.size >= page_size * mmap_window) { - unsigned long shift = page_size * (head / page_size); int ret; + shift = page_size * (head / page_size); + ret = munmap(buf, page_size * mmap_window); assert(ret == 0); @@ -1501,7 +1520,7 @@ static int __cmd_report(void) head += size; - if (offset + head >= sizeof(file_header) + file_header.data_size) + if (offset + head >= header->data_offset + header->data_size) goto done; if (offset + head < stat.st_size) diff --git a/tools/perf/perf.h b/tools/perf/perf.h index bccb529dac086..16c84fd73c86b 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -19,7 +19,7 @@ #include <sys/syscall.h> #include "../../include/linux/perf_counter.h" -#include "types.h" +#include "util/types.h" /* * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all @@ -66,10 +66,4 @@ sys_perf_counter_open(struct perf_counter_attr *attr, #define MAX_COUNTERS 256 #define MAX_NR_CPUS 256 -struct perf_file_header { - u64 version; - u64 sample_type; - u64 data_size; -}; - #endif diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c new file mode 100644 index 0000000000000..450384b3bbe53 --- /dev/null +++ b/tools/perf/util/header.c @@ -0,0 +1,242 @@ +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include "util.h" +#include "header.h" + +/* + * + */ + +struct perf_header_attr *perf_header_attr__new(struct perf_counter_attr *attr) +{ + struct perf_header_attr *self = malloc(sizeof(*self)); + + if (!self) + die("nomem"); + + self->attr = *attr; + self->ids = 0; + self->size = 1; + self->id = malloc(sizeof(u64)); + + if (!self->id) + die("nomem"); + + return self; +} + +void perf_header_attr__add_id(struct perf_header_attr *self, u64 id) +{ + int pos = self->ids; + + self->ids++; + if (self->ids > self->size) { + self->size *= 2; + self->id = realloc(self->id, self->size * sizeof(u64)); + if (!self->id) + die("nomem"); + } + self->id[pos] = id; +} + +/* + * + */ + +struct perf_header *perf_header__new(void) +{ + struct perf_header *self = malloc(sizeof(*self)); + + if (!self) + die("nomem"); + + self->frozen = 0; + + self->attrs = 0; + self->size = 1; + self->attr = malloc(sizeof(void *)); + + if (!self->attr) + die("nomem"); + + self->data_offset = 0; + self->data_size = 0; + + return self; +} + +void perf_header__add_attr(struct perf_header *self, + struct perf_header_attr *attr) +{ + int pos = self->attrs; + + if (self->frozen) + die("frozen"); + + self->attrs++; + if (self->attrs > self->size) { + self->size *= 2; + self->attr = realloc(self->attr, self->size * sizeof(void *)); + if (!self->attr) + die("nomem"); + } + self->attr[pos] = attr; +} + +static const char *__perf_magic = "PERFFILE"; + +#define PERF_MAGIC (*(u64 *)__perf_magic) + +struct perf_file_section { + u64 offset; + u64 size; +}; + +struct perf_file_attr { + struct perf_counter_attr attr; + struct perf_file_section ids; +}; + +struct perf_file_header { + u64 magic; + u64 size; + u64 attr_size; + struct perf_file_section attrs; + struct perf_file_section data; +}; + +static void do_write(int fd, void *buf, size_t size) +{ + while (size) { + int ret = write(fd, buf, size); + + if (ret < 0) + die("failed to write"); + + size -= ret; + buf += ret; + } +} + +void perf_header__write(struct perf_header *self, int fd) +{ + struct perf_file_header f_header; + struct perf_file_attr f_attr; + struct perf_header_attr *attr; + int i; + + lseek(fd, sizeof(f_header), SEEK_SET); + + + for (i = 0; i < self->attrs; i++) { + attr = self->attr[i]; + + attr->id_offset = lseek(fd, 0, SEEK_CUR); + do_write(fd, attr->id, attr->ids * sizeof(u64)); + } + + + self->attr_offset = lseek(fd, 0, SEEK_CUR); + + for (i = 0; i < self->attrs; i++) { + attr = self->attr[i]; + + f_attr = (struct perf_file_attr){ + .attr = attr->attr, + .ids = { + .offset = attr->id_offset, + .size = attr->ids * sizeof(u64), + } + }; + do_write(fd, &f_attr, sizeof(f_attr)); + } + + + self->data_offset = lseek(fd, 0, SEEK_CUR); + + f_header = (struct perf_file_header){ + .magic = PERF_MAGIC, + .size = sizeof(f_header), + .attr_size = sizeof(f_attr), + .attrs = { + .offset = self->attr_offset, + .size = self->attrs * sizeof(f_attr), + }, + .data = { + .offset = self->data_offset, + .size = self->data_size, + }, + }; + + lseek(fd, 0, SEEK_SET); + do_write(fd, &f_header, sizeof(f_header)); + lseek(fd, self->data_offset + self->data_size, SEEK_SET); + + self->frozen = 1; +} + +static void do_read(int fd, void *buf, size_t size) +{ + while (size) { + int ret = read(fd, buf, size); + + if (ret < 0) + die("failed to read"); + + size -= ret; + buf += ret; + } +} + +struct perf_header *perf_header__read(int fd) +{ + struct perf_header *self = perf_header__new(); + struct perf_file_header f_header; + struct perf_file_attr f_attr; + u64 f_id; + + int nr_attrs, nr_ids, i, j; + + lseek(fd, 0, SEEK_SET); + do_read(fd, &f_header, sizeof(f_header)); + + if (f_header.magic != PERF_MAGIC || + f_header.size != sizeof(f_header) || + f_header.attr_size != sizeof(f_attr)) + die("incompatible file format"); + + nr_attrs = f_header.attrs.size / sizeof(f_attr); + lseek(fd, f_header.attrs.offset, SEEK_SET); + + for (i = 0; i < nr_attrs; i++) { + struct perf_header_attr *attr; + off_t tmp = lseek(fd, 0, SEEK_CUR); + + do_read(fd, &f_attr, sizeof(f_attr)); + + attr = perf_header_attr__new(&f_attr.attr); + + nr_ids = f_attr.ids.size / sizeof(u64); + lseek(fd, f_attr.ids.offset, SEEK_SET); + + for (j = 0; j < nr_ids; j++) { + do_read(fd, &f_id, sizeof(f_id)); + + perf_header_attr__add_id(attr, f_id); + } + perf_header__add_attr(self, attr); + lseek(fd, tmp, SEEK_SET); + } + + self->data_offset = f_header.data.offset; + self->data_size = f_header.data.size; + + lseek(fd, self->data_offset + self->data_size, SEEK_SET); + + self->frozen = 1; + + return self; +} diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h new file mode 100644 index 0000000000000..b5ef53ad4c7a1 --- /dev/null +++ b/tools/perf/util/header.h @@ -0,0 +1,37 @@ +#ifndef _PERF_HEADER_H +#define _PERF_HEADER_H + +#include "../../../include/linux/perf_counter.h" +#include <sys/types.h> +#include "types.h" + +struct perf_header_attr { + struct perf_counter_attr attr; + int ids, size; + u64 *id; + off_t id_offset; +}; + +struct perf_header { + int frozen; + int attrs, size; + struct perf_header_attr **attr; + off_t attr_offset; + u64 data_offset; + u64 data_size; +}; + +struct perf_header *perf_header__read(int fd); +void perf_header__write(struct perf_header *self, int fd); + +void perf_header__add_attr(struct perf_header *self, + struct perf_header_attr *attr); + +struct perf_header_attr * +perf_header_attr__new(struct perf_counter_attr *attr); +void perf_header_attr__add_id(struct perf_header_attr *self, u64 id); + + +struct perf_header *perf_header__new(void); + +#endif /* _PERF_HEADER_H */ diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index 37b03255b425f..3dca2f654cd06 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h @@ -1,7 +1,7 @@ #ifndef _PERF_STRING_H_ #define _PERF_STRING_H_ -#include "../types.h" +#include "types.h" int hex2u64(const char *ptr, u64 *val); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index ea332e56e4582..940b432db16ed 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -2,7 +2,7 @@ #define _PERF_SYMBOL_ 1 #include <linux/types.h> -#include "../types.h" +#include "types.h" #include "list.h" #include "rbtree.h" diff --git a/tools/perf/types.h b/tools/perf/util/types.h similarity index 100% rename from tools/perf/types.h rename to tools/perf/util/types.h -- GitLab From 41f95331b972a039f519ae0c70f051b7121f7346 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Tue, 23 Jun 2009 17:55:18 +0200 Subject: [PATCH 0190/1002] perf_counter: Split the mmap control page in two parts Since there are two distinct sections to the control page, move them apart so that possible extentions don't overlap. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index e7213e46cf9c5..489d5cbfbcca3 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -233,6 +233,12 @@ struct perf_counter_mmap_page { __u32 index; /* hardware counter identifier */ __s64 offset; /* add to hardware counter value */ + /* + * Hole for extension of the self monitor capabilities + */ + + __u64 __reserved[125]; /* align to 1k */ + /* * Control data for the mmap() data buffer. * -- GitLab From 7f8b4e4e0988dadfd22330fd147ad2453e19f510 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Mon, 22 Jun 2009 14:34:35 +0200 Subject: [PATCH 0191/1002] perf_counter: Add scale information to the mmap control page Add the needed time scale to the self-profile mmap information. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 4 +++- kernel/perf_counter.c | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 489d5cbfbcca3..bcbf1c43ed422 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -232,12 +232,14 @@ struct perf_counter_mmap_page { __u32 lock; /* seqlock for synchronization */ __u32 index; /* hardware counter identifier */ __s64 offset; /* add to hardware counter value */ + __u64 time_enabled; /* time counter active */ + __u64 time_running; /* time counter on cpu */ /* * Hole for extension of the self monitor capabilities */ - __u64 __reserved[125]; /* align to 1k */ + __u64 __reserved[123]; /* align to 1k */ /* * Control data for the mmap() data buffer. diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index c2b19c1117187..23614adab475b 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1782,6 +1782,12 @@ void perf_counter_update_userpage(struct perf_counter *counter) if (counter->state == PERF_COUNTER_STATE_ACTIVE) userpg->offset -= atomic64_read(&counter->hw.prev_count); + userpg->time_enabled = counter->total_time_enabled + + atomic64_read(&counter->child_total_time_enabled); + + userpg->time_running = counter->total_time_running + + atomic64_read(&counter->child_total_time_running); + barrier(); ++userpg->lock; preempt_enable(); -- GitLab From 194002b274e9169a04beb1b23dcc132159bb566c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Mon, 22 Jun 2009 16:35:24 +0200 Subject: [PATCH 0192/1002] perf_counter, x86: Add mmap counter read support Update the mmap control page with the needed information to use the userspace RDPMC instruction for self monitoring. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/powerpc/include/asm/perf_counter.h | 2 ++ arch/x86/include/asm/perf_counter.h | 3 +++ arch/x86/kernel/cpu/perf_counter.c | 6 ++++++ kernel/perf_counter.c | 10 +++++++++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/perf_counter.h b/arch/powerpc/include/asm/perf_counter.h index 8ccd4e155768f..0ea0639fcf75b 100644 --- a/arch/powerpc/include/asm/perf_counter.h +++ b/arch/powerpc/include/asm/perf_counter.h @@ -61,6 +61,8 @@ struct pt_regs; extern unsigned long perf_misc_flags(struct pt_regs *regs); extern unsigned long perf_instruction_pointer(struct pt_regs *regs); +#define PERF_COUNTER_INDEX_OFFSET 1 + /* * Only override the default definitions in include/linux/perf_counter.h * if we have hardware PMU support. diff --git a/arch/x86/include/asm/perf_counter.h b/arch/x86/include/asm/perf_counter.h index 5fb33e160ea0b..fa64e401589d4 100644 --- a/arch/x86/include/asm/perf_counter.h +++ b/arch/x86/include/asm/perf_counter.h @@ -87,6 +87,9 @@ union cpuid10_edx { #ifdef CONFIG_PERF_COUNTERS extern void init_hw_perf_counters(void); extern void perf_counters_lapic_init(void); + +#define PERF_COUNTER_INDEX_OFFSET 0 + #else static inline void init_hw_perf_counters(void) { } static inline void perf_counters_lapic_init(void) { } diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index a310d19faca36..b83474b6021ad 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -912,6 +912,8 @@ x86_perf_counter_set_period(struct perf_counter *counter, err = checking_wrmsrl(hwc->counter_base + idx, (u64)(-left) & x86_pmu.counter_mask); + perf_counter_update_userpage(counter); + return ret; } @@ -1034,6 +1036,8 @@ static int x86_pmu_enable(struct perf_counter *counter) x86_perf_counter_set_period(counter, hwc, idx); x86_pmu.enable(hwc, idx); + perf_counter_update_userpage(counter); + return 0; } @@ -1126,6 +1130,8 @@ static void x86_pmu_disable(struct perf_counter *counter) x86_perf_counter_update(counter, hwc, idx); cpuc->counters[idx] = NULL; clear_bit(idx, cpuc->used_mask); + + perf_counter_update_userpage(counter); } /* diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 23614adab475b..02994a719e271 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1753,6 +1753,14 @@ int perf_counter_task_disable(void) return 0; } +static int perf_counter_index(struct perf_counter *counter) +{ + if (counter->state != PERF_COUNTER_STATE_ACTIVE) + return 0; + + return counter->hw.idx + 1 - PERF_COUNTER_INDEX_OFFSET; +} + /* * Callers need to ensure there can be no nesting of this function, otherwise * the seqlock logic goes bad. We can not serialize this because the arch @@ -1777,7 +1785,7 @@ void perf_counter_update_userpage(struct perf_counter *counter) preempt_disable(); ++userpg->lock; barrier(); - userpg->index = counter->hw.idx; + userpg->index = perf_counter_index(counter); userpg->offset = atomic64_read(&counter->count); if (counter->state == PERF_COUNTER_STATE_ACTIVE) userpg->offset -= atomic64_read(&counter->hw.prev_count); -- GitLab From 38b200d67636a30cb8dc1508137908e7a649b5c9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Tue, 23 Jun 2009 20:13:11 +0200 Subject: [PATCH 0193/1002] perf_counter: Add PERF_EVENT_READ Provide a read() like event which can be used to log the counter value at specific sites such as child->parent folding on exit. In order to be useful, we log the counter parent ID, not the actual counter ID, since userspace can only relate parent IDs to perf_counter_attr constructs. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 12 ++++++ kernel/perf_counter.c | 72 ++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index bcbf1c43ed422..6a384f04755ad 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -334,6 +334,18 @@ enum perf_event_type { */ PERF_EVENT_FORK = 7, + /* + * struct { + * struct perf_event_header header; + * u32 pid, tid; + * u64 value; + * { u64 time_enabled; } && PERF_FORMAT_ENABLED + * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 parent_id; } && PERF_FORMAT_ID + * }; + */ + PERF_EVENT_READ = 8, + /* * When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field * will be PERF_SAMPLE_* diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 02994a719e271..a72c20e91953c 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -2623,6 +2623,66 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, perf_output_end(&handle); } +/* + * read event + */ + +struct perf_read_event { + struct perf_event_header header; + + u32 pid; + u32 tid; + u64 value; + u64 format[3]; +}; + +static void +perf_counter_read_event(struct perf_counter *counter, + struct task_struct *task) +{ + struct perf_output_handle handle; + struct perf_read_event event = { + .header = { + .type = PERF_EVENT_READ, + .misc = 0, + .size = sizeof(event) - sizeof(event.format), + }, + .pid = perf_counter_pid(counter, task), + .tid = perf_counter_tid(counter, task), + .value = atomic64_read(&counter->count), + }; + int ret, i = 0; + + if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { + event.header.size += sizeof(u64); + event.format[i++] = counter->total_time_enabled; + } + + if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { + event.header.size += sizeof(u64); + event.format[i++] = counter->total_time_running; + } + + if (counter->attr.read_format & PERF_FORMAT_ID) { + u64 id; + + event.header.size += sizeof(u64); + if (counter->parent) + id = counter->parent->id; + else + id = counter->id; + + event.format[i++] = id; + } + + ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); + if (ret) + return; + + perf_output_copy(&handle, &event, event.header.size); + perf_output_end(&handle); +} + /* * fork tracking */ @@ -3985,10 +4045,13 @@ static int inherit_group(struct perf_counter *parent_counter, } static void sync_child_counter(struct perf_counter *child_counter, - struct perf_counter *parent_counter) + struct task_struct *child) { + struct perf_counter *parent_counter = child_counter->parent; u64 child_val; + perf_counter_read_event(child_counter, child); + child_val = atomic64_read(&child_counter->count); /* @@ -4017,7 +4080,8 @@ static void sync_child_counter(struct perf_counter *child_counter, static void __perf_counter_exit_task(struct perf_counter *child_counter, - struct perf_counter_context *child_ctx) + struct perf_counter_context *child_ctx, + struct task_struct *child) { struct perf_counter *parent_counter; @@ -4031,7 +4095,7 @@ __perf_counter_exit_task(struct perf_counter *child_counter, * counters need to be zapped - but otherwise linger. */ if (parent_counter) { - sync_child_counter(child_counter, parent_counter); + sync_child_counter(child_counter, child); free_counter(child_counter); } } @@ -4093,7 +4157,7 @@ void perf_counter_exit_task(struct task_struct *child) again: list_for_each_entry_safe(child_counter, tmp, &child_ctx->counter_list, list_entry) - __perf_counter_exit_task(child_counter, child_ctx); + __perf_counter_exit_task(child_counter, child_ctx, child); /* * If the last counter was a group counter, it will have appended all -- GitLab From bfbd3381e63aa2a14c6706afb50ce4630aa0d9a2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Wed, 24 Jun 2009 21:11:59 +0200 Subject: [PATCH 0194/1002] perf_counter: Implement more accurate per task statistics With the introduction of PERF_EVENT_READ we have the possibility to provide accurate counter values for individual tasks in a task hierarchy. However, due to the lazy context switching used for similar counter contexts our current per task counts are way off. In order to maintain some of the lazy switch benefits we don't disable it out-right, but simply iterate the active counters and flip the values between the contexts. This only reads the counters but does not need to reprogram the full PMU. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 4 +- kernel/perf_counter.c | 83 ++++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 6a384f04755ad..de70a10b5ec81 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -178,8 +178,9 @@ struct perf_counter_attr { mmap : 1, /* include mmap data */ comm : 1, /* include comm data */ freq : 1, /* use freq, not period */ + inherit_stat : 1, /* per task counts */ - __reserved_1 : 53; + __reserved_1 : 52; __u32 wakeup_events; /* wakeup every n events */ __u32 __reserved_2; @@ -602,6 +603,7 @@ struct perf_counter_context { int nr_counters; int nr_active; int is_active; + int nr_stat; atomic_t refcount; struct task_struct *task; diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index a72c20e91953c..385ca51c6e606 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -236,6 +236,8 @@ list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx) list_add_rcu(&counter->event_entry, &ctx->event_list); ctx->nr_counters++; + if (counter->attr.inherit_stat) + ctx->nr_stat++; } /* @@ -250,6 +252,8 @@ list_del_counter(struct perf_counter *counter, struct perf_counter_context *ctx) if (list_empty(&counter->list_entry)) return; ctx->nr_counters--; + if (counter->attr.inherit_stat) + ctx->nr_stat--; list_del_init(&counter->list_entry); list_del_rcu(&counter->event_entry); @@ -1006,6 +1010,76 @@ static int context_equiv(struct perf_counter_context *ctx1, && !ctx1->pin_count && !ctx2->pin_count; } +static void __perf_counter_read(void *counter); + +static void __perf_counter_sync_stat(struct perf_counter *counter, + struct perf_counter *next_counter) +{ + u64 value; + + if (!counter->attr.inherit_stat) + return; + + /* + * Update the counter value, we cannot use perf_counter_read() + * because we're in the middle of a context switch and have IRQs + * disabled, which upsets smp_call_function_single(), however + * we know the counter must be on the current CPU, therefore we + * don't need to use it. + */ + switch (counter->state) { + case PERF_COUNTER_STATE_ACTIVE: + __perf_counter_read(counter); + break; + + case PERF_COUNTER_STATE_INACTIVE: + update_counter_times(counter); + break; + + default: + break; + } + + /* + * In order to keep per-task stats reliable we need to flip the counter + * values when we flip the contexts. + */ + value = atomic64_read(&next_counter->count); + value = atomic64_xchg(&counter->count, value); + atomic64_set(&next_counter->count, value); + + /* + * XXX also sync time_enabled and time_running ? + */ +} + +#define list_next_entry(pos, member) \ + list_entry(pos->member.next, typeof(*pos), member) + +static void perf_counter_sync_stat(struct perf_counter_context *ctx, + struct perf_counter_context *next_ctx) +{ + struct perf_counter *counter, *next_counter; + + if (!ctx->nr_stat) + return; + + counter = list_first_entry(&ctx->event_list, + struct perf_counter, event_entry); + + next_counter = list_first_entry(&next_ctx->event_list, + struct perf_counter, event_entry); + + while (&counter->event_entry != &ctx->event_list && + &next_counter->event_entry != &next_ctx->event_list) { + + __perf_counter_sync_stat(counter, next_counter); + + counter = list_next_entry(counter, event_entry); + next_counter = list_next_entry(counter, event_entry); + } +} + /* * Called from scheduler to remove the counters of the current task, * with interrupts disabled. @@ -1061,6 +1135,8 @@ void perf_counter_task_sched_out(struct task_struct *task, ctx->task = next; next_ctx->task = task; do_switch = 0; + + perf_counter_sync_stat(ctx, next_ctx); } spin_unlock(&next_ctx->lock); spin_unlock(&ctx->lock); @@ -1350,7 +1426,7 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu) /* * Cross CPU call to read the hardware counter */ -static void __read(void *info) +static void __perf_counter_read(void *info) { struct perf_counter *counter = info; struct perf_counter_context *ctx = counter->ctx; @@ -1372,7 +1448,7 @@ static u64 perf_counter_read(struct perf_counter *counter) */ if (counter->state == PERF_COUNTER_STATE_ACTIVE) { smp_call_function_single(counter->oncpu, - __read, counter, 1); + __perf_counter_read, counter, 1); } else if (counter->state == PERF_COUNTER_STATE_INACTIVE) { update_counter_times(counter); } @@ -4050,7 +4126,8 @@ static void sync_child_counter(struct perf_counter *child_counter, struct perf_counter *parent_counter = child_counter->parent; u64 child_val; - perf_counter_read_event(child_counter, child); + if (child_counter->attr.inherit_stat) + perf_counter_read_event(child_counter, child); child_val = atomic64_read(&child_counter->count); -- GitLab From e6e18ec79b023d5fe84226cef533cf0e3770ce93 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Thu, 25 Jun 2009 11:27:12 +0200 Subject: [PATCH 0195/1002] perf_counter: Rework the sample ABI The PERF_EVENT_READ implementation made me realize we don't actually need the sample_type int the output sample, since we already have that in the perf_counter_attr information. Therefore, remove the PERF_EVENT_MISC_OVERFLOW bit and the event->type overloading, and imply put counter overflow samples in a PERF_EVENT_SAMPLE type. This also fixes the issue that event->type was only 32-bit and sample_type had 64 usable bits. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 10 +++++----- kernel/perf_counter.c | 36 +++++++++++++++-------------------- tools/perf/builtin-annotate.c | 8 ++++---- tools/perf/builtin-report.c | 32 ++++++++++++++++++------------- tools/perf/builtin-top.c | 11 ++++++----- 5 files changed, 49 insertions(+), 48 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index de70a10b5ec81..3078e23c91ebd 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -262,7 +262,6 @@ struct perf_counter_mmap_page { #define PERF_EVENT_MISC_KERNEL (1 << 0) #define PERF_EVENT_MISC_USER (2 << 0) #define PERF_EVENT_MISC_HYPERVISOR (3 << 0) -#define PERF_EVENT_MISC_OVERFLOW (1 << 2) struct perf_event_header { __u32 type; @@ -348,9 +347,6 @@ enum perf_event_type { PERF_EVENT_READ = 8, /* - * When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field - * will be PERF_SAMPLE_* - * * struct { * struct perf_event_header header; * @@ -358,8 +354,9 @@ enum perf_event_type { * { u32 pid, tid; } && PERF_SAMPLE_TID * { u64 time; } && PERF_SAMPLE_TIME * { u64 addr; } && PERF_SAMPLE_ADDR - * { u64 config; } && PERF_SAMPLE_CONFIG + * { u64 id; } && PERF_SAMPLE_ID * { u32 cpu, res; } && PERF_SAMPLE_CPU + * { u64 period; } && PERF_SAMPLE_PERIOD * * { u64 nr; * { u64 id, val; } cnt[nr]; } && PERF_SAMPLE_GROUP @@ -368,6 +365,9 @@ enum perf_event_type { * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN * }; */ + PERF_EVENT_SAMPLE = 9, + + PERF_EVENT_MAX, /* non-ABI */ }; enum perf_callchain_context { diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 385ca51c6e606..f2f2326965870 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -2575,15 +2575,14 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, u32 cpu, reserved; } cpu_entry; - header.type = 0; + header.type = PERF_EVENT_SAMPLE; header.size = sizeof(header); - header.misc = PERF_EVENT_MISC_OVERFLOW; + header.misc = 0; header.misc |= perf_misc_flags(data->regs); if (sample_type & PERF_SAMPLE_IP) { ip = perf_instruction_pointer(data->regs); - header.type |= PERF_SAMPLE_IP; header.size += sizeof(ip); } @@ -2592,7 +2591,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, tid_entry.pid = perf_counter_pid(counter, current); tid_entry.tid = perf_counter_tid(counter, current); - header.type |= PERF_SAMPLE_TID; header.size += sizeof(tid_entry); } @@ -2602,34 +2600,25 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, */ time = sched_clock(); - header.type |= PERF_SAMPLE_TIME; header.size += sizeof(u64); } - if (sample_type & PERF_SAMPLE_ADDR) { - header.type |= PERF_SAMPLE_ADDR; + if (sample_type & PERF_SAMPLE_ADDR) header.size += sizeof(u64); - } - if (sample_type & PERF_SAMPLE_ID) { - header.type |= PERF_SAMPLE_ID; + if (sample_type & PERF_SAMPLE_ID) header.size += sizeof(u64); - } if (sample_type & PERF_SAMPLE_CPU) { - header.type |= PERF_SAMPLE_CPU; header.size += sizeof(cpu_entry); cpu_entry.cpu = raw_smp_processor_id(); } - if (sample_type & PERF_SAMPLE_PERIOD) { - header.type |= PERF_SAMPLE_PERIOD; + if (sample_type & PERF_SAMPLE_PERIOD) header.size += sizeof(u64); - } if (sample_type & PERF_SAMPLE_GROUP) { - header.type |= PERF_SAMPLE_GROUP; header.size += sizeof(u64) + counter->nr_siblings * sizeof(group_entry); } @@ -2639,10 +2628,9 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, if (callchain) { callchain_size = (1 + callchain->nr) * sizeof(u64); - - header.type |= PERF_SAMPLE_CALLCHAIN; header.size += callchain_size; - } + } else + header.size += sizeof(u64); } ret = perf_output_begin(&handle, counter, header.size, nmi, 1); @@ -2693,8 +2681,14 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, } } - if (callchain) - perf_output_copy(&handle, callchain, callchain_size); + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + if (callchain) + perf_output_copy(&handle, callchain, callchain_size); + else { + u64 nr = 0; + perf_output_put(&handle, nr); + } + } perf_output_end(&handle); } diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 7e58e3ad15080..722c0f54e549e 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -855,7 +855,7 @@ static unsigned long total = 0, total_unknown = 0; static int -process_overflow_event(event_t *event, unsigned long offset, unsigned long head) +process_sample_event(event_t *event, unsigned long offset, unsigned long head) { char level; int show = 0; @@ -1013,10 +1013,10 @@ process_period_event(event_t *event, unsigned long offset, unsigned long head) static int process_event(event_t *event, unsigned long offset, unsigned long head) { - if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) - return process_overflow_event(event, offset, head); - switch (event->header.type) { + case PERF_EVENT_SAMPLE: + return process_sample_event(event, offset, head); + case PERF_EVENT_MMAP: return process_mmap_event(event, offset, head); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e575f30397669..ec5361c67bf5d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -53,6 +53,8 @@ static regex_t parent_regex; static int exclude_other = 1; +static u64 sample_type; + struct ip_event { struct perf_event_header header; u64 ip; @@ -1135,7 +1137,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event) } static int -process_overflow_event(event_t *event, unsigned long offset, unsigned long head) +process_sample_event(event_t *event, unsigned long offset, unsigned long head) { char level; int show = 0; @@ -1147,12 +1149,12 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head) void *more_data = event->ip.__more_data; struct ip_callchain *chain = NULL; - if (event->header.type & PERF_SAMPLE_PERIOD) { + if (sample_type & PERF_SAMPLE_PERIOD) { period = *(u64 *)more_data; more_data += sizeof(u64); } - dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n", + dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n", (void *)(offset + head), (void *)(long)(event->header.size), event->header.misc, @@ -1160,7 +1162,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head) (void *)(long)ip, (long long)period); - if (event->header.type & PERF_SAMPLE_CALLCHAIN) { + if (sample_type & PERF_SAMPLE_CALLCHAIN) { int i; chain = (void *)more_data; @@ -1352,10 +1354,10 @@ process_event(event_t *event, unsigned long offset, unsigned long head) { trace_event(event); - if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) - return process_overflow_event(event, offset, head); - switch (event->header.type) { + case PERF_EVENT_SAMPLE: + return process_sample_event(event, offset, head); + case PERF_EVENT_MMAP: return process_mmap_event(event, offset, head); @@ -1388,18 +1390,21 @@ process_event(event_t *event, unsigned long offset, unsigned long head) static struct perf_header *header; -static int perf_header__has_sample(u64 sample_mask) +static u64 perf_header__sample_type(void) { + u64 sample_type = 0; int i; for (i = 0; i < header->attrs; i++) { struct perf_header_attr *attr = header->attr[i]; - if (!(attr->attr.sample_type & sample_mask)) - return 0; + if (!sample_type) + sample_type = attr->attr.sample_type; + else if (sample_type != attr->attr.sample_type) + die("non matching sample_type"); } - return 1; + return sample_type; } static int __cmd_report(void) @@ -1437,8 +1442,9 @@ static int __cmd_report(void) header = perf_header__read(input); head = header->data_offset; - if (sort__has_parent && - !perf_header__has_sample(PERF_SAMPLE_CALLCHAIN)) { + sample_type = perf_header__sample_type(); + + if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { fprintf(stderr, "selected --sort parent, but no callchain data\n"); exit(-1); } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5352b5e352ed3..cf0d21f1ae10e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -392,11 +392,11 @@ static void record_ip(u64 ip, int counter) samples--; } -static void process_event(u64 ip, int counter) +static void process_event(u64 ip, int counter, int user) { samples++; - if (ip < min_ip || ip > max_ip) { + if (user) { userspace_samples++; return; } @@ -509,9 +509,10 @@ static void mmap_read_counter(struct mmap_data *md) old += size; - if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { - if (event->header.type & PERF_SAMPLE_IP) - process_event(event->ip.ip, md->counter); + if (event->header.type == PERF_EVENT_SAMPLE) { + int user = + (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER; + process_event(event->ip.ip, md->counter, user); } } -- GitLab From 649c48a9e7fafcc72bfcc99471d9dea98d789d59 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Wed, 24 Jun 2009 21:12:48 +0200 Subject: [PATCH 0196/1002] perf-report: Add modes for inherited stats and no-samples Now that we can collect per task statistics, add modes that make use of that facility. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-record.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f4f0240d2302a..798a56d890e5e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -41,6 +41,8 @@ static int force = 0; static int append_file = 0; static int call_graph = 0; static int verbose = 0; +static int inherit_stat = 0; +static int no_samples = 0; static long samples; static struct timeval last_read; @@ -393,6 +395,12 @@ static void create_counter(int counter, int cpu, pid_t pid) attr->sample_freq = freq; } + if (no_samples) + attr->sample_freq = 0; + + if (inherit_stat) + attr->inherit_stat = 1; + if (call_graph) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; @@ -571,7 +579,7 @@ static int __cmd_record(int argc, const char **argv) } } - while (!done) { + for (;;) { int hits = samples; for (i = 0; i < nr_cpu; i++) { @@ -579,8 +587,11 @@ static int __cmd_record(int argc, const char **argv) mmap_read(&mmap_array[i][counter]); } - if (hits == samples) + if (hits == samples) { + if (done) + break; ret = poll(event_array, nr_poll, 100); + } } /* @@ -629,6 +640,10 @@ static const struct option options[] = { "do call-graph (stack chain/backtrace) recording"), OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), + OPT_BOOLEAN('s', "stat", &inherit_stat, + "per thread counts"), + OPT_BOOLEAN('n', "no-samples", &no_samples, + "don't sample"), OPT_END() }; -- GitLab From e9ea2fde7a07ae60a119171a2946ed2ae778271e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Wed, 24 Jun 2009 22:46:04 +0200 Subject: [PATCH 0197/1002] perf-report: Add bare minimum PERF_EVENT_READ parsing Provide the basic infrastructure to provide per task stats. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ec5361c67bf5d..681c2233f8827 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -100,6 +100,13 @@ struct lost_event { u64 lost; }; +struct read_event { + struct perf_event_header header; + u32 pid,tid; + u64 value; + u64 format[3]; +}; + typedef union event_union { struct perf_event_header header; struct ip_event ip; @@ -108,6 +115,7 @@ typedef union event_union { struct fork_event fork; struct period_event period; struct lost_event lost; + struct read_event read; } event_t; static LIST_HEAD(dsos); @@ -1349,6 +1357,19 @@ static void trace_event(event_t *event) dprintf(".\n"); } +static int +process_read_event(event_t *event, unsigned long offset, unsigned long head) +{ + dprintf("%p [%p]: PERF_EVENT_READ: %d %d %Lu\n", + (void *)(offset + head), + (void *)(long)(event->header.size), + event->read.pid, + event->read.tid, + event->read.value); + + return 0; +} + static int process_event(event_t *event, unsigned long offset, unsigned long head) { @@ -1373,6 +1394,9 @@ process_event(event_t *event, unsigned long offset, unsigned long head) case PERF_EVENT_LOST: return process_lost_event(event, offset, head); + case PERF_EVENT_READ: + return process_read_event(event, offset, head); + /* * We dont process them right now but they are fine: */ -- GitLab From 4418351f06d9ce73acc846158c20186965f920f3 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 25 Jun 2009 21:27:42 +0530 Subject: [PATCH 0198/1002] perf_counter tools: Add alias for 'l1d' and 'l1i' Add 'l1d' and 'l1i' aliases again as shortcuts - just dont make them the primary display alias. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1245945462.9157.11.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 430f06083201a..4d042f104cdcf 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -71,8 +71,8 @@ static char *sw_event_names[] = { #define MAX_ALIASES 8 static char *hw_cache[][MAX_ALIASES] = { - { "L1-d$", "l1-d", "L1-data", }, - { "L1-i$", "l1-i", "L1-instruction", }, + { "L1-d$", "l1-d", "l1d", "L1-data", }, + { "L1-i$", "l1-i", "l1i", "L1-instruction", }, { "LLC", "L2" }, { "dTLB", "d-tlb", "Data-TLB", }, { "iTLB", "i-tlb", "Instruction-TLB", }, -- GitLab From 5211a242d0cbdded372aee59da18f80552b0a80a Mon Sep 17 00:00:00 2001 From: Kurt Garloff <garloff@suse.de> Date: Wed, 24 Jun 2009 14:32:11 -0700 Subject: [PATCH 0199/1002] x86: Add sysctl to allow panic on IOCK NMI error This patch introduces a new sysctl: /proc/sys/kernel/panic_on_io_nmi which defaults to 0 (off). When enabled, the kernel panics when the kernel receives an NMI caused by an IO error. The IO error triggered NMI indicates a serious system condition, which could result in IO data corruption. Rather than contiuing, panicing and dumping might be a better choice, so one can figure out what's causing the IO error. This could be especially important to companies running IO intensive applications where corruption must be avoided, e.g. a bank's databases. [ SuSE has been shipping it for a while, it was done at the request of a large database vendor, for their users. ] Signed-off-by: Kurt Garloff <garloff@suse.de> Signed-off-by: Roberto Angelino <robertangelino@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Cc: "Eric W. Biederman" <ebiederm@xmission.com> LKML-Reference: <20090624213211.GA11291@kroah.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/dumpstack.c | 1 + arch/x86/kernel/traps.c | 3 +++ include/linux/kernel.h | 1 + kernel/sysctl.c | 8 ++++++++ 4 files changed, 13 insertions(+) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 95ea5fa7d4445..c8405718a4c3b 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -22,6 +22,7 @@ #include "dumpstack.h" int panic_on_unrecovered_nmi; +int panic_on_io_nmi; unsigned int code_bytes = 64; int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; static int die_counter; diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a0f48f5671c07..5204332f475d8 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -346,6 +346,9 @@ io_check_error(unsigned char reason, struct pt_regs *regs) printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); + if (panic_on_io_nmi) + panic("NMI IOCK error: Not continuing"); + /* Re-enable the IOCK line, wait for a few seconds */ reason = (reason & 0xf) | 8; outb(reason, 0x61); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index fac104e7186ae..d6320a3e8def0 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -303,6 +303,7 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in extern int panic_timeout; extern int panic_on_oops; extern int panic_on_unrecovered_nmi; +extern int panic_on_io_nmi; extern const char *print_tainted(void); extern void add_taint(unsigned flag); extern int test_taint(unsigned flag); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 62e4ff9968b5f..fba42eda8de29 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -743,6 +743,14 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "panic_on_io_nmi", + .data = &panic_on_io_nmi, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = KERN_BOOTLOADER_TYPE, .procname = "bootloader_type", -- GitLab From 3928ddbe994cce1da1b6365b0db04d5765f254f4 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 25 Jun 2009 22:21:27 +0200 Subject: [PATCH 0200/1002] perf record: Fix unhandled io return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building latest perfcounter fails on the following error: builtin-record.c: In function ‘create_counter’: builtin-record.c:451: erreur: ignoring return value of ‘read’, declared with attribute warn_unused_result make: *** [builtin-record.o] Erreur 1 Just check if we successfully read the perf file descriptor. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <1245961287-5327-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-record.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 798a56d890e5e..d18546f37d7c5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -448,7 +448,10 @@ static void create_counter(int counter, int cpu, pid_t pid) } } - read(fd[nr_cpu][counter], &read_data, sizeof(read_data)); + if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) { + perror("Unable to read perf file descriptor\n"); + exit(-1); + } perf_header_attr__add_id(h_attr, read_data.id); -- GitLab From 5be6066a7f8d917db347d94f1b359b9b70dcb572 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Wed, 24 Jun 2009 09:21:10 +0900 Subject: [PATCH 0201/1002] x86, mce: percpu mcheck_timer should be pinned If CONFIG_NO_HZ + CONFIG_SMP, timer added via add_timer() might be migrated on other cpu. Use add_timer_on() instead. Avoids the following failure: Maciej Rutecki wrote: > > After normal boot I try: > > > > echo 1 > /sys/devices/system/machinecheck/machinecheck0/check_interval > > > > I found this in dmesg: > > > > [ 141.704025] ------------[ cut here ]------------ > > [ 141.704039] WARNING: at arch/x86/kernel/cpu/mcheck/mce.c:1102 > > mcheck_timer+0xf5/0x100() Reported-by: Maciej Rutecki <maciej.rutecki@gmail.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Tested-by: Maciej Rutecki <maciej.rutecki@gmail.com> Acked-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/kernel/cpu/mcheck/mce.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 284d1de968bc3..af425b83202b3 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1117,7 +1117,7 @@ static void mcheck_timer(unsigned long data) *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); t->expires = jiffies + *n; - add_timer(t); + add_timer_on(t, smp_processor_id()); } static void mce_do_trigger(struct work_struct *work) @@ -1321,7 +1321,7 @@ static void mce_init_timer(void) return; setup_timer(t, mcheck_timer, smp_processor_id()); t->expires = round_jiffies(jiffies + *n); - add_timer(t); + add_timer_on(t, smp_processor_id()); } /* -- GitLab From 22f4319d6bc0155e6c0ae560729baa6c09dc09e7 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" <rpjday@crashcourse.ca> Date: Thu, 25 Jun 2009 16:20:48 -0400 Subject: [PATCH 0202/1002] x86, setup: Fix typo "CONFIG_x86_64" in <asm/boot.h> CONFIG_X86_64 was misspelled (wrong case), which caused the x86-64 kernel to advertise itself as more relocatable than it really is. This could in theory cause boot failures once bootloaders start support the new relocation fields. Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/include/asm/boot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 418e632d4a801..6f02b9a53848a 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -16,7 +16,7 @@ & ~(CONFIG_PHYSICAL_ALIGN - 1)) /* Minimum kernel alignment, as a power of two */ -#ifdef CONFIG_x86_64 +#ifdef CONFIG_X86_64 #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT #else #define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT+1) -- GitLab From 658dbfeb5e7ab35d440c665d643a6285e43fddcd Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" <hpa@zytor.com> Date: Thu, 25 Jun 2009 15:16:06 -0700 Subject: [PATCH 0203/1002] x86, setup: correct include file in <asm/boot.h> <asm/boot.h> needs <asm/pgtable_types.h>, not <asm/page_types.h> in order to resolve PMD_SHIFT. Also, correct a +1 which really should be + THREAD_ORDER. This is a build error which was masked by a typoed #ifdef. Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/include/asm/boot.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 6f02b9a53848a..7a1065958ba9d 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -8,7 +8,7 @@ #ifdef __KERNEL__ -#include <asm/page_types.h> +#include <asm/pgtable_types.h> /* Physical address where kernel should be loaded. */ #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ @@ -19,7 +19,7 @@ #ifdef CONFIG_X86_64 #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT #else -#define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT+1) +#define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT + THREAD_ORDER) #endif #define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2) -- GitLab From e888d7facd1f1460a638151036d15b6cfb3ccc74 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> Date: Thu, 25 Jun 2009 16:44:31 -0700 Subject: [PATCH 0204/1002] x86, delay: tsc based udelay should have rdtsc_barrier delay_tsc needs rdtsc_barrier to provide proper delay. Output from a test driver using hpet to cross check delay provided by udelay(). Before: [ 86.794363] Expected delay 5us actual 4679ns [ 87.154362] Expected delay 5us actual 698ns [ 87.514162] Expected delay 5us actual 4539ns [ 88.653716] Expected delay 5us actual 4539ns [ 94.664106] Expected delay 10us actual 9638ns [ 95.049351] Expected delay 10us actual 10126ns [ 95.416110] Expected delay 10us actual 9568ns [ 95.799216] Expected delay 10us actual 9638ns [ 103.624104] Expected delay 10us actual 9707ns [ 104.020619] Expected delay 10us actual 768ns [ 104.419951] Expected delay 10us actual 9707ns After: [ 50.983320] Expected delay 5us actual 5587ns [ 51.261807] Expected delay 5us actual 5587ns [ 51.565715] Expected delay 5us actual 5657ns [ 51.861171] Expected delay 5us actual 5587ns [ 52.164704] Expected delay 5us actual 5726ns [ 52.487457] Expected delay 5us actual 5657ns [ 52.789338] Expected delay 5us actual 5726ns [ 57.119680] Expected delay 10us actual 10755ns [ 57.893997] Expected delay 10us actual 10615ns [ 58.261287] Expected delay 10us actual 10755ns [ 58.620505] Expected delay 10us actual 10825ns [ 58.941035] Expected delay 10us actual 10755ns [ 59.320903] Expected delay 10us actual 10615ns [ 61.306311] Expected delay 10us actual 10755ns [ 61.520542] Expected delay 10us actual 10615ns Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/lib/delay.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index f4568605d7d5c..ff485d361182f 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -55,8 +55,10 @@ static void delay_tsc(unsigned long loops) preempt_disable(); cpu = smp_processor_id(); + rdtsc_barrier(); rdtscl(bclock); for (;;) { + rdtsc_barrier(); rdtscl(now); if ((now - bclock) >= loops) break; @@ -78,6 +80,7 @@ static void delay_tsc(unsigned long loops) if (unlikely(cpu != smp_processor_id())) { loops -= (now - bclock); cpu = smp_processor_id(); + rdtsc_barrier(); rdtscl(bclock); } } -- GitLab From 14a2ff6ed28931f796d2c2c8a440227a5d90f441 Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Thu, 25 Jun 2009 19:00:47 -0700 Subject: [PATCH 0205/1002] sparc64: Don't use alloc_bootmem() in init_IRQ() code paths. The page allocator and SLAB are available at this point now, and if we still try to use bootmem allocations here the kernel spits out warnings. Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/kernel/irq_64.c | 45 ++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index bd075054942bd..f0ee79055409d 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -20,7 +20,6 @@ #include <linux/delay.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <linux/bootmem.h> #include <linux/irq.h> #include <asm/ptrace.h> @@ -914,25 +913,19 @@ void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) tb->nonresum_qmask); } -static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask) -{ - unsigned long size = PAGE_ALIGN(qmask + 1); - void *p = __alloc_bootmem(size, size, 0); - if (!p) { - prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); - prom_halt(); - } - - *pa_ptr = __pa(p); -} - -static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask) +/* Each queue region must be a power of 2 multiple of 64 bytes in + * size. The base real address must be aligned to the size of the + * region. Thus, an 8KB queue must be 8KB aligned, for example. + */ +static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask) { unsigned long size = PAGE_ALIGN(qmask + 1); - void *p = __alloc_bootmem(size, size, 0); + unsigned long order = get_order(size); + unsigned long p; + p = __get_free_pages(GFP_KERNEL, order); if (!p) { - prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); + prom_printf("SUN4V: Error, cannot allocate queue.\n"); prom_halt(); } @@ -942,11 +935,11 @@ static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask) static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) { #ifdef CONFIG_SMP - void *page; + unsigned long page; BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); - page = alloc_bootmem_pages(PAGE_SIZE); + page = get_zeroed_page(GFP_KERNEL); if (!page) { prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); prom_halt(); @@ -965,13 +958,13 @@ static void __init sun4v_init_mondo_queues(void) for_each_possible_cpu(cpu) { struct trap_per_cpu *tb = &trap_block[cpu]; - alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask); - alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask); - alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask); - alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask); - alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask); - alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, - tb->nonresum_qmask); + alloc_one_queue(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask); + alloc_one_queue(&tb->dev_mondo_pa, tb->dev_mondo_qmask); + alloc_one_queue(&tb->resum_mondo_pa, tb->resum_qmask); + alloc_one_queue(&tb->resum_kernel_buf_pa, tb->resum_qmask); + alloc_one_queue(&tb->nonresum_mondo_pa, tb->nonresum_qmask); + alloc_one_queue(&tb->nonresum_kernel_buf_pa, + tb->nonresum_qmask); } } @@ -999,7 +992,7 @@ void __init init_IRQ(void) kill_prom_timer(); size = sizeof(struct ino_bucket) * NUM_IVECS; - ivector_table = alloc_bootmem(size); + ivector_table = kzalloc(size, GFP_KERNEL); if (!ivector_table) { prom_printf("Fatal error, cannot allocate ivector_table\n"); prom_halt(); -- GitLab From 413ee282a510afb2f18975a189501f39d279a906 Mon Sep 17 00:00:00 2001 From: Julian Calaby <julian.calaby@gmail.com> Date: Sun, 21 Jun 2009 16:44:13 +0000 Subject: [PATCH 0206/1002] sparc64: Fix build warnings in piggyback_64.c This patch fixes the following build warnings: arch/sparc/boot/piggyback_64.c: In function 'main': arch/sparc/boot/piggyback_64.c:44: warning: 'end' may be used uninitialized in this function arch/sparc/boot/piggyback_64.c:44: warning: 'start' may be used uninitialized in this function Signed-off-by: Julian Calaby <julian.calaby@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/boot/piggyback_64.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sparc/boot/piggyback_64.c b/arch/sparc/boot/piggyback_64.c index de364bfed0bbf..c63fd1b6bdd4f 100644 --- a/arch/sparc/boot/piggyback_64.c +++ b/arch/sparc/boot/piggyback_64.c @@ -46,6 +46,7 @@ int main(int argc,char **argv) struct stat s; int image, tail; + start = end = 0; if (stat (argv[3], &s) < 0) die (argv[3]); map = fopen (argv[2], "r"); if (!map) die(argv[2]); -- GitLab From 22b096a8907e5184f25fafd1b73f0b3633d52495 Mon Sep 17 00:00:00 2001 From: Robert Reif <reif@earthlink.net> Date: Sun, 21 Jun 2009 16:45:44 +0000 Subject: [PATCH 0207/1002] sparc32: Fix obvious build issues for tftpboot.img build. Signed-off-by: Robert Reif <reif@earthlink.net> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/boot/Makefile | 2 +- arch/sparc/boot/piggyback_32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 96041a8d39e8c..5e2caeb31109e 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -58,7 +58,7 @@ $(obj)/image: $(obj)/btfix.o FORCE $(obj)/zImage: $(obj)/image $(call if_changed,strip) -$(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE +$(obj)/tftpboot.img: $(obj)/piggyback_32 $(obj)/System.map $(obj)/image FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index c9f500c1a8b23..3f0f933545432 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -70,7 +70,7 @@ void die(char *str) int main(int argc,char **argv) { static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; - unsigned char buffer[1024], *q, *r; + char buffer[1024], *q, *r; unsigned int i, j, k, start, end, offset; FILE *map; struct stat s; -- GitLab From 52da82cfb569b44e26e15395a6727277758580fe Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 21 Jun 2009 16:46:10 +0000 Subject: [PATCH 0208/1002] sparc: fix tftpboot.img build Kjetil Oftedal mentioned that piggyback_32 was failing when building a sparc image. I tracked this down to the fact that the kernel no longer provided an absolute symbol named "end". Commit 86ed40bd6fe511d26bb8f3fa65a84cb65c235366 ("sparc: unify sections.h") renamed end to _end but failed to update piggyback_32. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Cc: Kjetil Oftedal <oftedal@gmail.com> Cc: Robert Reif <reif@earthlink.net> Signed-off-by: Julian Calaby <julian.calaby@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/boot/piggyback_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index 3f0f933545432..e8dc9adfcd61d 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -84,7 +84,7 @@ int main(int argc,char **argv) while (fgets (buffer, 1024, map)) { if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) start = strtoul (buffer, NULL, 16); - else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n")) + else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n")) end = strtoul (buffer, NULL, 16); } fclose (map); -- GitLab From 3e05c5e2ce40066582dc34aa8335baa328815a09 Mon Sep 17 00:00:00 2001 From: Julian Calaby <julian.calaby@gmail.com> Date: Sun, 21 Jun 2009 16:45:01 +0000 Subject: [PATCH 0209/1002] sparc32: Fix tftpboot.img Makefile Signed-off-by: Julian Calaby <julian.calaby@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/boot/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 5e2caeb31109e..500a2f87f28f0 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -15,7 +15,7 @@ quiet_cmd_elftoaout = ELFTOAOUT $@ ifeq ($(CONFIG_SPARC32),y) quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback_32 $@ $(obj)/System.map $(ROOT_IMG) + cmd_piggy = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG) quiet_cmd_btfix = BTFIX $@ cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map @@ -58,7 +58,7 @@ $(obj)/image: $(obj)/btfix.o FORCE $(obj)/zImage: $(obj)/image $(call if_changed,strip) -$(obj)/tftpboot.img: $(obj)/piggyback_32 $(obj)/System.map $(obj)/image FORCE +$(obj)/tftpboot.img: $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) -- GitLab From 8944146daa2c38dd85bc489d1b84fb9abc108837 Mon Sep 17 00:00:00 2001 From: Julian Calaby <julian.calaby@gmail.com> Date: Tue, 23 Jun 2009 01:45:46 +0000 Subject: [PATCH 0210/1002] sparc32: Fix makefile not generating required files The tftpboot build was failing with missing file errors. It turns out that $(obj)/image wasn't being generated which was causing the a.out conversion to be skipped and hence piggyback to be called with nonexistent files. Signed-off-by: Julian Calaby <julian.calaby@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/sparc/boot/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 500a2f87f28f0..1ff0fd9247565 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -58,7 +58,7 @@ $(obj)/image: $(obj)/btfix.o FORCE $(obj)/zImage: $(obj)/image $(call if_changed,strip) -$(obj)/tftpboot.img: $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE +$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) @@ -79,7 +79,7 @@ $(obj)/image: vmlinux FORCE $(call if_changed,strip) @echo ' kernel: $@ is ready' -$(obj)/tftpboot.img: vmlinux $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE +$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) @echo ' kernel: $@ is ready' -- GitLab From 1ac530b3553e0b4dc1e18a32bed57cfa84cd57cb Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Wed, 24 Jun 2009 22:29:31 +0000 Subject: [PATCH 0211/1002] tcp: missing check ACK flag of received segment in FIN-WAIT-2 state RFC0793 defined that in FIN-WAIT-2 state if the ACK bit is off drop the segment and return[Page 72]. But this check is missing in function tcp_timewait_state_process(). This cause the segment with FIN flag but no ACK has two diffent action: Case 1: Node A Node B <------------- FIN,ACK (enter FIN-WAIT-1) ACK -------------> (enter FIN-WAIT-2) FIN -------------> discard (move sk to tw list) Case 2: Node A Node B <------------- FIN,ACK (enter FIN-WAIT-1) ACK -------------> (enter FIN-WAIT-2) (move sk to tw list) FIN -------------> <------------- ACK This patch fixed the problem. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/tcp_minisocks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 43bbba7926ee4..f8d67ccc64f32 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -128,7 +128,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, goto kill_with_rst; /* Dup ACK? */ - if (!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || + if (!th->ack || + !after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) { inet_twsk_put(tw); return TCP_TW_SUCCESS; -- GitLab From a1faa69810b2af562b70b2a71c116c7d03575dd3 Mon Sep 17 00:00:00 2001 From: Jens Rosenboom <me@jayr.de> Date: Thu, 25 Jun 2009 04:55:50 +0000 Subject: [PATCH 0212/1002] ipv6: avoid wraparound for expired preferred lifetime Avoid showing wrong high values when the preferred lifetime of an address is expired. Signed-off-by: Jens Rosenboom <me@jayr.de> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv6/addrconf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8c1e86afbbf52..3883b4036a74c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3362,7 +3362,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, valid = ifa->valid_lft; if (preferred != INFINITY_LIFE_TIME) { long tval = (jiffies - ifa->tstamp)/HZ; - preferred -= tval; + if (preferred > tval) + preferred -= tval; + else + preferred = 0; if (valid != INFINITY_LIFE_TIME) valid -= tval; } -- GitLab From e2a61fa31382b1ac2b22f76f9c439892e5dc4b86 Mon Sep 17 00:00:00 2001 From: Ionut Nicu <ionut.nicu@freescale.com> Date: Wed, 24 Jun 2009 22:23:39 +0000 Subject: [PATCH 0213/1002] fsl_pq_mdio: Fix fsl_pq_mdio to work with modules This patch fixes the case when ucc_geth or gianfar are compiled as modules. Without this patch the call to phy_connect() fails. Signed-off-by: Ionut Nicu <ionut.nicu@freescale.com> Acked-by: Andy Fleming <afleming@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/fsl_pq_mdio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index 3af581303ca2b..d167090248e2f 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -188,7 +188,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) } -#ifdef CONFIG_GIANFAR +#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) { struct gfar __iomem *enet_regs; @@ -206,7 +206,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs) #endif -#ifdef CONFIG_UCC_GETH +#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) { struct device_node *np = NULL; @@ -291,7 +291,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, if (of_device_is_compatible(np, "fsl,gianfar-mdio") || of_device_is_compatible(np, "fsl,gianfar-tbi") || of_device_is_compatible(np, "gianfar")) { -#ifdef CONFIG_GIANFAR +#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) tbipa = get_gfar_tbipa(regs); #else err = -ENODEV; @@ -299,7 +299,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev, #endif } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || of_device_is_compatible(np, "ucc_geth_phy")) { -#ifdef CONFIG_UCC_GETH +#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) u32 id; static u32 mii_mng_master; -- GitLab From 37c8ae3acf39108b3b7866897f1e3e9f277efc50 Mon Sep 17 00:00:00 2001 From: roel kluin <roel.kluin@gmail.com> Date: Mon, 22 Jun 2009 07:38:00 +0000 Subject: [PATCH 0214/1002] sh_eth: remove redundant test on unsigned Unsigned boguscnt cannot be less than 0. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/sh_eth.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 341882f959f3c..a2d82ddb3b4d7 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -865,8 +865,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_cpu_data *cd = mdp->cd; irqreturn_t ret = IRQ_NONE; - u32 ioaddr, boguscnt = RX_RING_SIZE; - u32 intr_status = 0; + u32 ioaddr, intr_status = 0; ioaddr = ndev->base_addr; spin_lock(&mdp->lock); @@ -901,12 +900,6 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) if (intr_status & cd->eesr_err_check) sh_eth_error(ndev, intr_status); - if (--boguscnt < 0) { - printk(KERN_WARNING - "%s: Too much work at interrupt, status=0x%4.4x.\n", - ndev->name, intr_status); - } - other_irq: spin_unlock(&mdp->lock); -- GitLab From 30767636e5896c650f33db5f7f0a9b0e82f3e8c4 Mon Sep 17 00:00:00 2001 From: Nicolas Reinecke <nr@das-labor.org> Date: Thu, 25 Jun 2009 02:55:31 +0000 Subject: [PATCH 0215/1002] mdio add missing GPL flag Add missing GPL flag and description. mdio: module license 'unspecified' taints kernel. Disabling lock debugging due to kernel taint Signed-off-by: Nicolas Reinecke <nr <at> das-labor.org> Acked-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/mdio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index dc45e9856c35b..6851bdb2ce299 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -14,6 +14,10 @@ #include <linux/mdio.h> #include <linux/module.h> +MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers"); +MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc."); +MODULE_LICENSE("GPL"); + /** * mdio45_probe - probe for an MDIO (clause 45) device * @mdio: MDIO interface -- GitLab From ad8034f19792736db5c259103c2eaaf72887bbb4 Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Fri, 26 Jun 2009 03:25:49 +0000 Subject: [PATCH 0216/1002] [CIFS] remove bkl usage from umount begin The lock_kernel call moved into the fs for umount_begin is not needed. This adds a check to make sure we don't call umount_begin twice on the same fs. umount_begin for cifs is probably not needed and may eventually be able to be removed, but in the meantime this smaller patch is safe and gets rid of the bkl from this path which provides some benefit. Acked-by: Jeff Layton <redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b5e9f398c2e58..9f669f982c4d4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -537,9 +537,14 @@ static void cifs_umount_begin(struct super_block *sb) if (tcon == NULL) return; - lock_kernel(); read_lock(&cifs_tcp_ses_lock); - if (tcon->tc_count == 1) + if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { + /* we have other mounts to same share or we have + already tried to force umount this and woken up + all waiting network requests, nothing to do */ + read_unlock(&cifs_tcp_ses_lock); + return; + } else if (tcon->tc_count == 1) tcon->tidStatus = CifsExiting; read_unlock(&cifs_tcp_ses_lock); @@ -554,9 +559,7 @@ static void cifs_umount_begin(struct super_block *sb) wake_up_all(&tcon->ses->server->response_q); msleep(1); } -/* BB FIXME - finish add checks for tidStatus BB */ - unlock_kernel(); return; } -- GitLab From 71a394faaad07090af5de5c075ec2f5bca0fbb35 Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Fri, 26 Jun 2009 04:07:18 +0000 Subject: [PATCH 0217/1002] [CIFS] remove unknown mount option warning message Jeff's previous patch which removed the unneeded rw/ro parsing can cause a minor warning in dmesg (about the unknown rw or ro mount option) at mount time. This patch makes cifs ignore them in kernel to remove the warning (they are already handled in the mount helper and VFS). Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/connect.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 12c2cf693555a..e16d7592116ad 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1196,6 +1196,10 @@ cifs_parse_mount_options(char *options, const char *devname, /* ignore */ } else if (strnicmp(data, "guest", 5) == 0) { /* ignore */ + } else if (strnicmp(data, "rw", 2) == 0) { + /* ignore */ + } else if (strnicmp(data, "ro", 2) == 0) { + /* ignore */ } else if (strnicmp(data, "noblocksend", 11) == 0) { vol->noblocksnd = 1; } else if (strnicmp(data, "noautotune", 10) == 0) { -- GitLab From 2b121bc262fa03c94e653b2d44356c2f86c1bcdc Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:36 +0200 Subject: [PATCH 0218/1002] eeepc-laptop: Register as a pci-hotplug device The eee contains a logically (but not physically) hotpluggable PCIe slot. Currently this is handled by adding or removing the PCI device in response to rfkill events, but if a user has forced pciehp to bind to it (with the force=1 argument) then both drivers will try to handle the event and hilarity (in the form of oopses) will ensue. This can be avoided by having eee-laptop register the slot as a hotplug slot. Only one of pciehp and eee-laptop will successfully register this, avoiding the problem. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Tested-by: Darren Salt <linux@youmustbejoking.demon.co.uk> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/Kconfig | 2 + drivers/platform/x86/eeepc-laptop.c | 87 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7232fe7104aa1..fee6a4022bc17 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -357,6 +357,8 @@ config EEEPC_LAPTOP depends on RFKILL || RFKILL = n select BACKLIGHT_CLASS_DEVICE select HWMON + select HOTPLUG + select HOTPLUG_PCI if PCI ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4207b26ff9906..c0b203ca29fbb 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -31,6 +31,7 @@ #include <linux/input.h> #include <linux/rfkill.h> #include <linux/pci.h> +#include <linux/pci_hotplug.h> #define EEEPC_LAPTOP_VERSION "0.1" @@ -143,6 +144,7 @@ struct eeepc_hotk { u16 *keycode_map; struct rfkill *eeepc_wlan_rfkill; struct rfkill *eeepc_bluetooth_rfkill; + struct hotplug_slot *hotplug_slot; }; /* The actual device the driver binds to */ @@ -213,6 +215,15 @@ static struct acpi_driver eeepc_hotk_driver = { }, }; +/* PCI hotplug ops */ +static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); + +static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { + .owner = THIS_MODULE, + .get_adapter_status = eeepc_get_adapter_status, + .get_power_status = eeepc_get_adapter_status, +}; + /* The backlight device /sys/class/backlight */ static struct backlight_device *eeepc_backlight_device; @@ -612,6 +623,19 @@ static int notify_brn(void) return -1; } +static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, + u8 *value) +{ + int val = get_acpi(CM_ASL_WLAN); + + if (val == 1 || val == 0) + *value = val; + else + return -EINVAL; + + return 0; +} + static void eeepc_rfkill_hotplug(void) { struct pci_dev *dev; @@ -744,6 +768,54 @@ static void eeepc_unregister_rfkill_notifier(char *node) } } +static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) +{ + kfree(hotplug_slot->info); + kfree(hotplug_slot); +} + +static int eeepc_setup_pci_hotplug(void) +{ + int ret = -ENOMEM; + struct pci_bus *bus = pci_find_bus(0, 1); + + if (!bus) { + printk(EEEPC_ERR "Unable to find wifi PCI bus\n"); + return -ENODEV; + } + + ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); + if (!ehotk->hotplug_slot) + goto error_slot; + + ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), + GFP_KERNEL); + if (!ehotk->hotplug_slot->info) + goto error_info; + + ehotk->hotplug_slot->private = ehotk; + ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; + ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; + eeepc_get_adapter_status(ehotk->hotplug_slot, + &ehotk->hotplug_slot->info->adapter_status); + + ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); + if (ret) { + printk(EEEPC_ERR "Unable to register hotplug slot - %d\n", ret); + goto error_register; + } + + return 0; + +error_register: + kfree(ehotk->hotplug_slot->info); +error_info: + kfree(ehotk->hotplug_slot); + ehotk->hotplug_slot = NULL; +error_slot: + return ret; +} + static int eeepc_hotk_add(struct acpi_device *device) { int result; @@ -802,8 +874,21 @@ static int eeepc_hotk_add(struct acpi_device *device) goto bluetooth_fail; } + result = eeepc_setup_pci_hotplug(); + /* + * If we get -EBUSY then something else is handling the PCI hotplug - + * don't fail in this case + */ + if (result == -EBUSY) + return 0; + else if (result) + goto pci_fail; + return 0; + pci_fail: + if (ehotk->eeepc_bluetooth_rfkill) + rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); bluetooth_fail: rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); rfkill_unregister(ehotk->eeepc_wlan_rfkill); @@ -825,6 +910,8 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); + if (ehotk->hotplug_slot) + pci_hp_deregister(ehotk->hotplug_slot); kfree(ehotk); return 0; -- GitLab From 19b532892834b7f1c04b2940ac73177dc566fed5 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Thu, 25 Jun 2009 13:25:37 +0200 Subject: [PATCH 0219/1002] eeepc-laptop.c: use pr_fmt and pr_<level> Convert the unusual printk(EEEPC_<level> uses to the more standard pr_fmt and pr_<level>(. Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 55 ++++++++++++----------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index c0b203ca29fbb..d14f7149cb131 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -16,6 +16,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -41,11 +43,6 @@ #define EEEPC_HOTK_DEVICE_NAME "Hotkey" #define EEEPC_HOTK_HID "ASUS010" -#define EEEPC_LOG EEEPC_HOTK_FILE ": " -#define EEEPC_ERR KERN_ERR EEEPC_LOG -#define EEEPC_WARNING KERN_WARNING EEEPC_LOG -#define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG -#define EEEPC_INFO KERN_INFO EEEPC_LOG /* * Definitions for Asus EeePC @@ -285,7 +282,7 @@ static int set_acpi(int cm, int value) if (method == NULL) return -ENODEV; if (write_acpi_int(ehotk->handle, method, value, NULL)) - printk(EEEPC_WARNING "Error writing %s\n", method); + pr_warning("Error writing %s\n", method); } return 0; } @@ -298,7 +295,7 @@ static int get_acpi(int cm) if (method == NULL) return -ENODEV; if (read_acpi_int(ehotk->handle, method, &value)) - printk(EEEPC_WARNING "Error reading %s\n", method); + pr_warning("Error reading %s\n", method); } return value; } @@ -562,26 +559,23 @@ static int eeepc_hotk_check(void) if (ehotk->device->status.present) { if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, &buffer)) { - printk(EEEPC_ERR "Hotkey initialization failed\n"); + pr_err("Hotkey initialization failed\n"); return -ENODEV; } else { - printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", - ehotk->init_flag); + pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); } /* get control methods supported */ if (read_acpi_int(ehotk->handle, "CMSG" , &ehotk->cm_supported)) { - printk(EEEPC_ERR - "Get control methods supported failed\n"); + pr_err("Get control methods supported failed\n"); return -ENODEV; } else { - printk(EEEPC_INFO - "Get control methods supported: 0x%x\n", - ehotk->cm_supported); + pr_info("Get control methods supported: 0x%x\n", + ehotk->cm_supported); } ehotk->inputdev = input_allocate_device(); if (!ehotk->inputdev) { - printk(EEEPC_INFO "Unable to allocate input device\n"); + pr_info("Unable to allocate input device\n"); return 0; } ehotk->inputdev->name = "Asus EeePC extra buttons"; @@ -600,12 +594,12 @@ static int eeepc_hotk_check(void) } result = input_register_device(ehotk->inputdev); if (result) { - printk(EEEPC_INFO "Unable to register input device\n"); + pr_info("Unable to register input device\n"); input_free_device(ehotk->inputdev); return 0; } } else { - printk(EEEPC_ERR "Hotkey device not present, aborting\n"); + pr_err("Hotkey device not present, aborting\n"); return -EINVAL; } return 0; @@ -643,7 +637,7 @@ static void eeepc_rfkill_hotplug(void) bool blocked; if (!bus) { - printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); + pr_warning("Unable to find PCI bus 1?\n"); return; } @@ -659,7 +653,7 @@ static void eeepc_rfkill_hotplug(void) if (dev) { pci_bus_assign_resources(bus); if (pci_bus_add_device(dev)) - printk(EEEPC_ERR "Unable to hotplug wifi\n"); + pr_err("Unable to hotplug wifi\n"); } } else { dev = pci_get_slot(bus, 0); @@ -742,8 +736,7 @@ static int eeepc_register_rfkill_notifier(char *node) eeepc_rfkill_notify, NULL); if (ACPI_FAILURE(status)) - printk(EEEPC_WARNING - "Failed to register notify on %s\n", node); + pr_warning("Failed to register notify on %s\n", node); } else return -ENODEV; @@ -762,8 +755,7 @@ static void eeepc_unregister_rfkill_notifier(char *node) ACPI_SYSTEM_NOTIFY, eeepc_rfkill_notify); if (ACPI_FAILURE(status)) - printk(EEEPC_ERR - "Error removing rfkill notify handler %s\n", + pr_err("Error removing rfkill notify handler %s\n", node); } } @@ -780,7 +772,7 @@ static int eeepc_setup_pci_hotplug(void) struct pci_bus *bus = pci_find_bus(0, 1); if (!bus) { - printk(EEEPC_ERR "Unable to find wifi PCI bus\n"); + pr_err("Unable to find wifi PCI bus\n"); return -ENODEV; } @@ -801,7 +793,7 @@ static int eeepc_setup_pci_hotplug(void) ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); if (ret) { - printk(EEEPC_ERR "Unable to register hotplug slot - %d\n", ret); + pr_err("Unable to register hotplug slot - %d\n", ret); goto error_register; } @@ -822,7 +814,7 @@ static int eeepc_hotk_add(struct acpi_device *device) if (!device) return -EINVAL; - printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); + pr_notice(EEEPC_HOTK_NAME "\n"); ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); if (!ehotk) return -ENOMEM; @@ -1105,8 +1097,7 @@ static int eeepc_backlight_init(struct device *dev) bd = backlight_device_register(EEEPC_HOTK_FILE, dev, NULL, &eeepcbl_ops); if (IS_ERR(bd)) { - printk(EEEPC_ERR - "Could not register eeepc backlight device\n"); + pr_err("Could not register eeepc backlight device\n"); eeepc_backlight_device = NULL; return PTR_ERR(bd); } @@ -1125,8 +1116,7 @@ static int eeepc_hwmon_init(struct device *dev) hwmon = hwmon_device_register(dev); if (IS_ERR(hwmon)) { - printk(EEEPC_ERR - "Could not register eeepc hwmon device\n"); + pr_err("Could not register eeepc hwmon device\n"); eeepc_hwmon_device = NULL; return PTR_ERR(hwmon); } @@ -1159,8 +1149,7 @@ static int __init eeepc_laptop_init(void) if (result) goto fail_backlight; } else - printk(EEEPC_INFO "Backlight controlled by ACPI video " - "driver\n"); + pr_info("Backlight controlled by ACPI video driver\n"); result = eeepc_hwmon_init(dev); if (result) -- GitLab From 7de39389d8f61aa517ce2a8b4d925acc62696ae5 Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:38 +0200 Subject: [PATCH 0220/1002] eeepc-laptop: rfkill refactoring Refactor rfkill code, because we'll add another rfkill for wwan3g later. Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 160 +++++++++++++++------------- 1 file changed, 84 insertions(+), 76 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index d14f7149cb131..e46981a5f20be 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -139,8 +139,8 @@ struct eeepc_hotk { u16 event_count[128]; /* count for each event */ struct input_dev *inputdev; u16 *keycode_map; - struct rfkill *eeepc_wlan_rfkill; - struct rfkill *eeepc_bluetooth_rfkill; + struct rfkill *wlan_rfkill; + struct rfkill *bluetooth_rfkill; struct hotplug_slot *hotplug_slot; }; @@ -663,7 +663,7 @@ static void eeepc_rfkill_hotplug(void) } } - rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); + rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); } static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) @@ -828,66 +828,8 @@ static int eeepc_hotk_add(struct acpi_device *device) if (result) goto ehotk_fail; - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); - - if (get_acpi(CM_ASL_WLAN) != -1) { - ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", - &device->dev, - RFKILL_TYPE_WLAN, - &eeepc_rfkill_ops, - (void *)CM_ASL_WLAN); - - if (!ehotk->eeepc_wlan_rfkill) - goto wlan_fail; - - rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, - get_acpi(CM_ASL_WLAN) != 1); - result = rfkill_register(ehotk->eeepc_wlan_rfkill); - if (result) - goto wlan_fail; - } - - if (get_acpi(CM_ASL_BLUETOOTH) != -1) { - ehotk->eeepc_bluetooth_rfkill = - rfkill_alloc("eeepc-bluetooth", - &device->dev, - RFKILL_TYPE_BLUETOOTH, - &eeepc_rfkill_ops, - (void *)CM_ASL_BLUETOOTH); - - if (!ehotk->eeepc_bluetooth_rfkill) - goto bluetooth_fail; - - rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, - get_acpi(CM_ASL_BLUETOOTH) != 1); - result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); - if (result) - goto bluetooth_fail; - } - - result = eeepc_setup_pci_hotplug(); - /* - * If we get -EBUSY then something else is handling the PCI hotplug - - * don't fail in this case - */ - if (result == -EBUSY) - return 0; - else if (result) - goto pci_fail; - return 0; - pci_fail: - if (ehotk->eeepc_bluetooth_rfkill) - rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); - bluetooth_fail: - rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); - rfkill_unregister(ehotk->eeepc_wlan_rfkill); - wlan_fail: - rfkill_destroy(ehotk->eeepc_wlan_rfkill); - eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); - eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); ehotk_fail: kfree(ehotk); ehotk = NULL; @@ -900,18 +842,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) if (!device || !acpi_driver_data(device)) return -EINVAL; - eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); - eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); - if (ehotk->hotplug_slot) - pci_hp_deregister(ehotk->hotplug_slot); - kfree(ehotk); return 0; } static int eeepc_hotk_resume(struct acpi_device *device) { - if (ehotk->eeepc_wlan_rfkill) { + if (ehotk->wlan_rfkill) { bool wlan; /* Workaround - it seems that _PTS disables the wireless @@ -923,14 +860,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) wlan = get_acpi(CM_ASL_WLAN); set_acpi(CM_ASL_WLAN, wlan); - rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, - wlan != 1); + rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); eeepc_rfkill_hotplug(); } - if (ehotk->eeepc_bluetooth_rfkill) - rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, + if (ehotk->bluetooth_rfkill) + rfkill_set_sw_state(ehotk->bluetooth_rfkill, get_acpi(CM_ASL_BLUETOOTH) != 1); return 0; @@ -1052,10 +988,14 @@ static void eeepc_backlight_exit(void) static void eeepc_rfkill_exit(void) { - if (ehotk->eeepc_wlan_rfkill) - rfkill_unregister(ehotk->eeepc_wlan_rfkill); - if (ehotk->eeepc_bluetooth_rfkill) - rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); + if (ehotk->wlan_rfkill) + rfkill_unregister(ehotk->wlan_rfkill); + if (ehotk->bluetooth_rfkill) + rfkill_unregister(ehotk->bluetooth_rfkill); + if (ehotk->hotplug_slot) + pci_hp_deregister(ehotk->hotplug_slot); } static void eeepc_input_exit(void) @@ -1090,6 +1030,67 @@ static void __exit eeepc_laptop_exit(void) platform_driver_unregister(&platform_driver); } +static int eeepc_new_rfkill(struct rfkill **rfkill, + const char *name, struct device *dev, + enum rfkill_type type, int cm) +{ + int result; + + if (get_acpi(cm) == -1) + return -ENODEV; + + *rfkill = rfkill_alloc(name, dev, type, + &eeepc_rfkill_ops, (void *)(unsigned long)cm); + + if (!*rfkill) + return -EINVAL; + + rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); + result = rfkill_register(*rfkill); + if (result) { + rfkill_destroy(*rfkill); + *rfkill = NULL; + return result; + } + return 0; +} + + +static int eeepc_rfkill_init(struct device *dev) +{ + int result = 0; + + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); + + result = eeepc_new_rfkill(&ehotk->wlan_rfkill, + "eeepc-wlan", dev, + RFKILL_TYPE_WLAN, CM_ASL_WLAN); + + if (result && result != -ENODEV) + goto exit; + + result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, + "eeepc-bluetooth", dev, + RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); + + if (result && result != -ENODEV) + goto exit; + + result = eeepc_setup_pci_hotplug(); + /* + * If we get -EBUSY then something else is handling the PCI hotplug - + * don't fail in this case + */ + if (result == -EBUSY) + result = 0; + +exit: + if (result && result != -ENODEV) + eeepc_rfkill_exit(); + return result; +} + static int eeepc_backlight_init(struct device *dev) { struct backlight_device *bd; @@ -1173,7 +1174,15 @@ static int __init eeepc_laptop_init(void) &platform_attribute_group); if (result) goto fail_sysfs; + + result = eeepc_rfkill_init(dev); + if (result) + goto fail_rfkill; + return 0; +fail_rfkill: + sysfs_remove_group(&platform_device->dev.kobj, + &platform_attribute_group); fail_sysfs: platform_device_del(platform_device); fail_platform_device2: @@ -1186,7 +1195,6 @@ static int __init eeepc_laptop_init(void) eeepc_backlight_exit(); fail_backlight: eeepc_input_exit(); - eeepc_rfkill_exit(); return result; } -- GitLab From 1ddec2f9435e77b4d3f50eced68c4c942f2bcd4b Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:39 +0200 Subject: [PATCH 0221/1002] eeepc-laptop: right parent device Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 34 +++++++++++++++-------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e46981a5f20be..5b102c2f66a0d 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1143,18 +1143,6 @@ static int __init eeepc_laptop_init(void) acpi_bus_unregister_driver(&eeepc_hotk_driver); return -ENODEV; } - dev = acpi_get_physical_device(ehotk->device->handle); - - if (!acpi_video_backlight_support()) { - result = eeepc_backlight_init(dev); - if (result) - goto fail_backlight; - } else - pr_info("Backlight controlled by ACPI video driver\n"); - - result = eeepc_hwmon_init(dev); - if (result) - goto fail_hwmon; eeepc_enable_camera(); @@ -1175,12 +1163,30 @@ static int __init eeepc_laptop_init(void) if (result) goto fail_sysfs; + dev = &platform_device->dev; + + if (!acpi_video_backlight_support()) { + result = eeepc_backlight_init(dev); + if (result) + goto fail_backlight; + } else + pr_info("Backlight controlled by ACPI video " + "driver\n"); + + result = eeepc_hwmon_init(dev); + if (result) + goto fail_hwmon; + result = eeepc_rfkill_init(dev); if (result) goto fail_rfkill; return 0; fail_rfkill: + eeepc_hwmon_exit(); +fail_hwmon: + eeepc_backlight_exit(); +fail_backlight: sysfs_remove_group(&platform_device->dev.kobj, &platform_attribute_group); fail_sysfs: @@ -1190,10 +1196,6 @@ static int __init eeepc_laptop_init(void) fail_platform_device1: platform_driver_unregister(&platform_driver); fail_platform_driver: - eeepc_hwmon_exit(); -fail_hwmon: - eeepc_backlight_exit(); -fail_backlight: eeepc_input_exit(); return result; } -- GitLab From f36509e7248631671d02f48d1a88f56cdeb54ed8 Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:40 +0200 Subject: [PATCH 0222/1002] eeepc-laptop: makes get_acpi() returns -ENODEV If there is there is no getter defined, get_acpi() will return -ENODEV. Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5b102c2f66a0d..19cc9ae7db5a7 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -289,7 +289,7 @@ static int set_acpi(int cm, int value) static int get_acpi(int cm) { - int value = -1; + int value = -ENODEV; if ((ehotk->cm_supported & (0x1 << cm))) { const char *method = cm_getv[cm]; if (method == NULL) @@ -367,13 +367,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) rv = parse_arg(buf, count, &value); if (rv > 0) - set_acpi(cm, value); + value = set_acpi(cm, value); + if (value < 0) + return value; return rv; } static ssize_t show_sys_acpi(int cm, char *buf) { - return sprintf(buf, "%d\n", get_acpi(cm)); + int value = get_acpi(cm); + + if (value < 0) + return value; + return sprintf(buf, "%d\n", value); } #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ @@ -1036,8 +1042,9 @@ static int eeepc_new_rfkill(struct rfkill **rfkill, { int result; - if (get_acpi(cm) == -1) - return -ENODEV; + result = get_acpi(cm); + if (result < 0) + return result; *rfkill = rfkill_alloc(name, dev, type, &eeepc_rfkill_ops, (void *)(unsigned long)cm); -- GitLab From dbfa3ba90dfe353a56e107cff5bce9fb7976f06f Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:41 +0200 Subject: [PATCH 0223/1002] eeepc-laptop: get the right value for CMSG CMSG is an ACPI method used to find features available on an Eee PC. But some features are never repported, even if present. If the getter of a feature is present, this patch will set the corresponding bit in cmsg. Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 19cc9ae7db5a7..f5d8473ea66f0 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -553,6 +553,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) return -EINVAL; } +static void cmsg_quirk(int cm, const char *name) +{ + int dummy; + + /* Some BIOSes do not report cm although it is avaliable. + Check if cm_getv[cm] works and, if yes, assume cm should be set. */ + if (!(ehotk->cm_supported & (1 << cm)) + && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { + pr_info("%s (%x) not reported by BIOS," + " enabling anyway\n", name, 1 << cm); + ehotk->cm_supported |= 1 << cm; + } +} + +static void cmsg_quirks(void) +{ + cmsg_quirk(CM_ASL_LID, "LID"); + cmsg_quirk(CM_ASL_TYPE, "TYPE"); + cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); + cmsg_quirk(CM_ASL_TPD, "TPD"); +} + static int eeepc_hotk_check(void) { const struct key_entry *key; @@ -576,6 +598,7 @@ static int eeepc_hotk_check(void) pr_err("Get control methods supported failed\n"); return -ENODEV; } else { + cmsg_quirks(); pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported); } -- GitLab From 3cd530b5aaffd27b231f9717730f2f6684c00bda Mon Sep 17 00:00:00 2001 From: Corentin Chary <corentincj@iksaif.net> Date: Thu, 25 Jun 2009 13:25:42 +0200 Subject: [PATCH 0224/1002] eeepc-laptop: add rfkill support for the 3G modem in Eee PC 901 Go Signed-off-by: Janne Grunau <j@jannau.net> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index f5d8473ea66f0..ec560f16d7204 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -141,6 +141,7 @@ struct eeepc_hotk { u16 *keycode_map; struct rfkill *wlan_rfkill; struct rfkill *bluetooth_rfkill; + struct rfkill *wwan3g_rfkill; struct hotplug_slot *hotplug_slot; }; @@ -1023,6 +1024,8 @@ static void eeepc_rfkill_exit(void) rfkill_unregister(ehotk->wlan_rfkill); if (ehotk->bluetooth_rfkill) rfkill_unregister(ehotk->bluetooth_rfkill); + if (ehotk->wwan3g_rfkill) + rfkill_unregister(ehotk->wwan3g_rfkill); if (ehotk->hotplug_slot) pci_hp_deregister(ehotk->hotplug_slot); } @@ -1107,6 +1110,13 @@ static int eeepc_rfkill_init(struct device *dev) if (result && result != -ENODEV) goto exit; + result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, + "eeepc-wwan3g", dev, + RFKILL_TYPE_WWAN, CM_ASL_3G); + + if (result && result != -ENODEV) + goto exit; + result = eeepc_setup_pci_hotplug(); /* * If we get -EBUSY then something else is handling the PCI hotplug - -- GitLab From 412af97838828bc6d035a1902c8974f944663da6 Mon Sep 17 00:00:00 2001 From: Troy Moure <twmoure@szypr.net> Date: Thu, 25 Jun 2009 17:05:35 -0600 Subject: [PATCH 0225/1002] ACPI: video: prevent NULL deref in acpi_get_pci_dev() ref: http://thread.gmane.org/gmane.linux.kernel/857228/focus=857468 When the ACPI video driver initializes, it does a namespace walk looking for for supported devices. When we find an appropriate handle, we walk up the ACPI tree looking for a PCI root bus, and then walk back down the PCI bus, assuming that every device inbetween is a P2P bridge. This assumption is not correct, and is reported broken on at least: Dell Latitude E6400 ThinkPad X61 Dell XPS M1330 Add a NULL deref check to prevent boot panics. Reported-by: Alessandro Suardi <alessandro.suardi@gmail.com> Signed-off-by: Troy Moure <twmoure@szypr.net> Signed-off-by: Alex Chiang <achiang@hp.com> Signed-off-by: Len Brown <len.brown@intel.com> --- drivers/acpi/pci_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 8a5bf3b356faa..55b5b90c2a442 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -395,7 +395,7 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle) fn = adr & 0xffff; pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); - if (hnd == handle) + if (!pdev || hnd == handle) break; pbus = pdev->subordinate; -- GitLab From 6f0b1c6094b3e8eeeb13f8f16c1b2ef452a6f519 Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Mon, 22 Jun 2009 23:13:48 +0000 Subject: [PATCH 0226/1002] powerpc: Swiotlb breaks pseries Turning on SWIOTLB selects or enables PPC_NEED_DMA_SYNC_OPS, which means we get the non empty versions of dma_sync_* in asm/dma-mapping.h On my pseries machine the dma_ops have no such routines and we die with a null pointer - this patch gets it booting, is there a more elegant way to do it? Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/dma-mapping.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 3d9e887c3c0cf..b44aaabdd1a68 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -309,7 +309,9 @@ static inline void dma_sync_single_for_cpu(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0, + + if (dma_ops->sync_single_range_for_cpu) + dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0, size, direction); } @@ -320,7 +322,9 @@ static inline void dma_sync_single_for_device(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_single_range_for_device(dev, dma_handle, + + if (dma_ops->sync_single_range_for_device) + dma_ops->sync_single_range_for_device(dev, dma_handle, 0, size, direction); } @@ -331,7 +335,9 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction); + + if (dma_ops->sync_sg_for_cpu) + dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction); } static inline void dma_sync_sg_for_device(struct device *dev, @@ -341,7 +347,9 @@ static inline void dma_sync_sg_for_device(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_sg_for_device(dev, sgl, nents, direction); + + if (dma_ops->sync_sg_for_device) + dma_ops->sync_sg_for_device(dev, sgl, nents, direction); } static inline void dma_sync_single_range_for_cpu(struct device *dev, @@ -351,7 +359,9 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_single_range_for_cpu(dev, dma_handle, + + if (dma_ops->sync_single_range_for_cpu) + dma_ops->sync_single_range_for_cpu(dev, dma_handle, offset, size, direction); } @@ -362,7 +372,9 @@ static inline void dma_sync_single_range_for_device(struct device *dev, struct dma_mapping_ops *dma_ops = get_dma_ops(dev); BUG_ON(!dma_ops); - dma_ops->sync_single_range_for_device(dev, dma_handle, offset, + + if (dma_ops->sync_single_range_for_device) + dma_ops->sync_single_range_for_device(dev, dma_handle, offset, size, direction); } #else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */ -- GitLab From 5a2642f620eb6e40792822fa0eafe23046fbb55e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Mon, 22 Jun 2009 16:47:59 +0000 Subject: [PATCH 0227/1002] powerpc/mpic: Fix mapping of "DCR" based MPIC variants Commit 31207dab7d2e63795eb15823947bd2f7025b08e2 "Fix incorrect allocation of interrupt rev-map" introduced a regression crashing on boot on machines using a "DCR" based MPIC, such as the Cell blades. The reason is that the irq host data structure is initialized much later as a result of that patch, causing our calls to mpic_map() do be done before we have a host setup. Unfortunately, this breaks _mpic_map_dcr() which uses the mpic->irqhost to get to the device node. This fixes it by, instead, passing the device node explicitely to mpic_map(). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Acked-by: Akira Tsukamoto <akirat@rd.scei.sony.co.jp> --- arch/powerpc/sysdev/mpic.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 9c3af5045495b..32a2e950f5638 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -279,28 +279,29 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr, } #ifdef CONFIG_PPC_DCR -static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, +static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, + struct mpic_reg_bank *rb, unsigned int offset, unsigned int size) { const u32 *dbasep; - dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL); + dbasep = of_get_property(node, "dcr-reg", NULL); - rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size); + rb->dhost = dcr_map(node, *dbasep + offset, size); BUG_ON(!DCR_MAP_OK(rb->dhost)); } -static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr, - struct mpic_reg_bank *rb, unsigned int offset, - unsigned int size) +static inline void mpic_map(struct mpic *mpic, struct device_node *node, + phys_addr_t phys_addr, struct mpic_reg_bank *rb, + unsigned int offset, unsigned int size) { if (mpic->flags & MPIC_USES_DCR) - _mpic_map_dcr(mpic, rb, offset, size); + _mpic_map_dcr(mpic, node, rb, offset, size); else _mpic_map_mmio(mpic, phys_addr, rb, offset, size); } #else /* CONFIG_PPC_DCR */ -#define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) +#define mpic_map(m,n,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) #endif /* !CONFIG_PPC_DCR */ @@ -1152,8 +1153,8 @@ struct mpic * __init mpic_alloc(struct device_node *node, } /* Map the global registers */ - mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); - mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); + mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); + mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); /* Reset */ if (flags & MPIC_WANTS_RESET) { @@ -1194,7 +1195,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic_map(mpic, paddr, &mpic->cpuregs[i], + mpic_map(mpic, node, paddr, &mpic->cpuregs[i], MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), 0x1000); } @@ -1202,7 +1203,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic_map(mpic, paddr, &mpic->isus[0], + mpic_map(mpic, node, paddr, &mpic->isus[0], MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); } mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); @@ -1256,8 +1257,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, BUG_ON(isu_num >= MPIC_MAX_ISU); - mpic_map(mpic, paddr, &mpic->isus[isu_num], 0, + mpic_map(mpic, mpic->irqhost->of_node, + paddr, &mpic->isus[isu_num], 0, MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); + if ((isu_first + mpic->isu_size) > mpic->num_sources) mpic->num_sources = isu_first + mpic->isu_size; } -- GitLab From b810c6ec5c659c80b3641580b112db877a0f1f45 Mon Sep 17 00:00:00 2001 From: Jon Smirl <jonsmirl@gmail.com> Date: Sun, 21 Jun 2009 15:28:00 +0000 Subject: [PATCH 0228/1002] powerpc: Have git ignore generated files from dtc compile Have git ignore generated files from dtc compile Signed-off-by: Jon Smirl <jonsmirl@gmail.com> Acked-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: Sean MacLennan <smaclennan@pikatech.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/boot/.gitignore | 10 ++++++++++ scripts/dtc/.gitignore | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 scripts/dtc/.gitignore diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 2f50acd11a602..3d80c3e9cf600 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore @@ -36,3 +36,13 @@ zImage.pseries zconf.h zlib.h zutil.h +fdt.c +fdt.h +fdt_ro.c +fdt_rw.c +fdt_strerror.c +fdt_sw.c +fdt_wip.c +libfdt.h +libfdt_internal.h + diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore new file mode 100644 index 0000000000000..095acb49a374b --- /dev/null +++ b/scripts/dtc/.gitignore @@ -0,0 +1,5 @@ +dtc +dtc-lexer.lex.c +dtc-parser.tab.c +dtc-parser.tab.h + -- GitLab From 3984114f056203d833251af85501721f7b00fd18 Mon Sep 17 00:00:00 2001 From: Sean MacLennan <smaclennan@pikatech.com> Date: Fri, 19 Jun 2009 19:43:59 +0000 Subject: [PATCH 0229/1002] powerpc/warp: Platform fix for i2c change A change to the i2c subsystem breaks the warp platform code. The patch is cleaner anyway, the old way was a bit crufty. For those with keen eyes, the gratuitous change in the string from PIKA to Warp is just so the logs look a bit nicer. The following two lines tend to be printed one after another. Warp POST OK Warp DTM thread running. Yeah, this will be the third patch to warp.c submitted in this release.... Cheers, Sean The i2c_client struct changed, breaking the code that looked for the ad7414 chip. Use the new of_find_i2c_device_by_node function added in 2.6.29. Signed-off-by: Sean MacLennan <smaclennan@pikatech.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/44x/warp.c | 44 ++++++++++--------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 42e09a9f77e26..0362c88f47d72 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/of_gpio.h> +#include <linux/of_i2c.h> #include <asm/machdep.h> #include <asm/prom.h> @@ -65,7 +66,6 @@ define_machine(warp) { static u32 post_info; -/* I am not sure this is the best place for this... */ static int __init warp_post_info(void) { struct device_node *np; @@ -194,9 +194,9 @@ static int pika_setup_leds(void) return 0; } -static void pika_setup_critical_temp(struct i2c_client *client) +static void pika_setup_critical_temp(struct device_node *np, + struct i2c_client *client) { - struct device_node *np; int irq, rc; /* Do this before enabling critical temp interrupt since we @@ -208,14 +208,7 @@ static void pika_setup_critical_temp(struct i2c_client *client) i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */ i2c_smbus_write_byte_data(client, 3, 0); /* Tlow */ - np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); - if (np == NULL) { - printk(KERN_ERR __FILE__ ": Unable to find ad7414\n"); - return; - } - irq = irq_of_parse_and_map(np, 0); - of_node_put(np); if (irq == NO_IRQ) { printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n"); return; @@ -244,32 +237,24 @@ static inline void pika_dtm_check_fan(void __iomem *fpga) static int pika_dtm_thread(void __iomem *fpga) { - struct i2c_adapter *adap; + struct device_node *np; struct i2c_client *client; - /* We loop in case either driver was compiled as a module and - * has not been insmoded yet. - */ - while (!(adap = i2c_get_adapter(0))) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - } - - while (1) { - list_for_each_entry(client, &adap->clients, list) - if (client->addr == 0x4a) - goto found_it; + np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); + if (np == NULL) + return -ENOENT; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + client = of_find_i2c_device_by_node(np); + if (client == NULL) { + of_node_put(np); + return -ENOENT; } -found_it: - pika_setup_critical_temp(client); + pika_setup_critical_temp(np, client); - i2c_put_adapter(adap); + of_node_put(np); - printk(KERN_INFO "PIKA DTM thread running.\n"); + printk(KERN_INFO "Warp DTM thread running.\n"); while (!kthread_should_stop()) { int val; @@ -291,7 +276,6 @@ static int pika_dtm_thread(void __iomem *fpga) return 0; } - static int __init pika_dtm_start(void) { struct task_struct *dtm_thread; -- GitLab From 6bb2ae535f2eee0334802724a542701bd969d055 Mon Sep 17 00:00:00 2001 From: Gerhard Pircher <gerhard_pircher@gmx.net> Date: Fri, 19 Jun 2009 11:42:36 +0000 Subject: [PATCH 0230/1002] powerpc/amigaone: Limit ISA I/O range to 4k in the device tree The kernel reserves the I/O address space from 0x0 to 0xfff for legacy ISA devices. Change the ranges property for the PCI2ISA bridge to match the kernels behavior, even if the ranges property isn't used for now. Signed-off-by: Gerhard Pircher <gerhard_pircher@gmx.net> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/boot/dts/amigaone.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/boot/dts/amigaone.dts b/arch/powerpc/boot/dts/amigaone.dts index 26549fca2ed44..49ac36b16dd78 100644 --- a/arch/powerpc/boot/dts/amigaone.dts +++ b/arch/powerpc/boot/dts/amigaone.dts @@ -70,8 +70,8 @@ isa@7 { devsel-speed = <0x00000001>; min-grant = <0>; max-latency = <0>; - /* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */ - ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00010000>; + /* First 4k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */ + ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>; interrupt-parent = <&i8259>; #interrupt-cells = <2>; #address-cells = <2>; -- GitLab From 7ccbe504b5ee766d33211a507189a06f3079b29b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Thu, 18 Jun 2009 23:30:07 +0000 Subject: [PATCH 0231/1002] powerpc/pmac: Fix issues with PowerMac "PowerSurge" SMP The old PowerSurge SMP (ie, dual or quad 604 machines) code has numerous issues in modern world. One is cpu_possible_map is set too late (the device-tree is bogus) so we fail to allocate the interrupt stacks and crash. Another problem is the fact the timebase is frozen by the bringup of the second CPU so the delays in the generic code will hang, we need to move some of the calling procedure to inside the powermac code. This makes it boot again for me Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/smp.c | 3 +- arch/powerpc/platforms/powermac/setup.c | 41 ++---- arch/powerpc/platforms/powermac/smp.c | 166 +++++++++++++++--------- 3 files changed, 112 insertions(+), 98 deletions(-) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 65484b2200b36..0b47de07302d1 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -68,7 +68,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); /* SMP operations for this machine */ struct smp_ops_t *smp_ops; -static volatile unsigned int cpu_callin_map[NR_CPUS]; +/* Can't be static due to PowerMac hackery */ +volatile unsigned int cpu_callin_map[NR_CPUS]; int smt_enabled_at_boot = 1; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 86f69a4eb49bf..c20522656367c 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -103,11 +103,6 @@ unsigned long smu_cmdbuf_abs; EXPORT_SYMBOL(smu_cmdbuf_abs); #endif -#ifdef CONFIG_SMP -extern struct smp_ops_t psurge_smp_ops; -extern struct smp_ops_t core99_smp_ops; -#endif /* CONFIG_SMP */ - static void pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; @@ -341,34 +336,6 @@ static void __init pmac_setup_arch(void) ROOT_DEV = DEFAULT_ROOT_DEVICE; #endif -#ifdef CONFIG_SMP - /* Check for Core99 */ - ic = of_find_node_by_name(NULL, "uni-n"); - if (!ic) - ic = of_find_node_by_name(NULL, "u3"); - if (!ic) - ic = of_find_node_by_name(NULL, "u4"); - if (ic) { - of_node_put(ic); - smp_ops = &core99_smp_ops; - } -#ifdef CONFIG_PPC32 - else { - /* - * We have to set bits in cpu_possible_map here since the - * secondary CPU(s) aren't in the device tree, and - * setup_per_cpu_areas only allocates per-cpu data for - * CPUs in the cpu_possible_map. - */ - int cpu; - - for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu) - cpu_set(cpu, cpu_possible_map); - smp_ops = &psurge_smp_ops; - } -#endif -#endif /* CONFIG_SMP */ - #ifdef CONFIG_ADB if (strstr(cmd_line, "adb_sync")) { extern int __adb_probe_sync; @@ -512,6 +479,14 @@ static void __init pmac_init_early(void) #ifdef CONFIG_PPC64 iommu_init_early_dart(); #endif + + /* SMP Init has to be done early as we need to patch up + * cpu_possible_map before interrupt stacks are allocated + * or kaboom... + */ +#ifdef CONFIG_SMP + pmac_setup_smp(); +#endif } static int __init pmac_declare_of_platform_devices(void) diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index cf1dbe758890d..6d4da7b46b419 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -64,10 +64,11 @@ extern void __secondary_start_pmac_0(void); extern int pmac_pfunc_base_install(void); -#ifdef CONFIG_PPC32 +static void (*pmac_tb_freeze)(int freeze); +static u64 timebase; +static int tb_req; -/* Sync flag for HW tb sync */ -static volatile int sec_tb_reset = 0; +#ifdef CONFIG_PPC32 /* * Powersurge (old powermac SMP) support. @@ -294,6 +295,9 @@ static int __init smp_psurge_probe(void) psurge_quad_init(); /* All released cards using this HW design have 4 CPUs */ ncpus = 4; + /* No sure how timebase sync works on those, let's use SW */ + smp_ops->give_timebase = smp_generic_give_timebase; + smp_ops->take_timebase = smp_generic_take_timebase; } else { iounmap(quad_base); if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { @@ -308,18 +312,15 @@ static int __init smp_psurge_probe(void) psurge_start = ioremap(PSURGE_START, 4); psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); - /* - * This is necessary because OF doesn't know about the + /* This is necessary because OF doesn't know about the * secondary cpu(s), and thus there aren't nodes in the * device tree for them, and smp_setup_cpu_maps hasn't - * set their bits in cpu_possible_map and cpu_present_map. + * set their bits in cpu_present_map. */ if (ncpus > NR_CPUS) ncpus = NR_CPUS; - for (i = 1; i < ncpus ; ++i) { + for (i = 1; i < ncpus ; ++i) cpu_set(i, cpu_present_map); - set_hard_smp_processor_id(i, i); - } if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); @@ -329,8 +330,14 @@ static int __init smp_psurge_probe(void) static void __init smp_psurge_kick_cpu(int nr) { unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; - unsigned long a; - int i; + unsigned long a, flags; + int i, j; + + /* Defining this here is evil ... but I prefer hiding that + * crap to avoid giving people ideas that they can do the + * same. + */ + extern volatile unsigned int cpu_callin_map[NR_CPUS]; /* may need to flush here if secondary bats aren't setup */ for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) @@ -339,47 +346,52 @@ static void __init smp_psurge_kick_cpu(int nr) if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); + /* This is going to freeze the timeebase, we disable interrupts */ + local_irq_save(flags); + out_be32(psurge_start, start); mb(); psurge_set_ipi(nr); + /* * We can't use udelay here because the timebase is now frozen. */ for (i = 0; i < 2000; ++i) - barrier(); + asm volatile("nop" : : : "memory"); psurge_clr_ipi(nr); - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); -} - -/* - * With the dual-cpu powersurge board, the decrementers and timebases - * of both cpus are frozen after the secondary cpu is started up, - * until we give the secondary cpu another interrupt. This routine - * uses this to get the timebases synchronized. - * -- paulus. - */ -static void __init psurge_dual_sync_tb(int cpu_nr) -{ - int t; - - set_dec(tb_ticks_per_jiffy); - /* XXX fixme */ - set_tb(0, 0); - - if (cpu_nr > 0) { + /* + * Also, because the timebase is frozen, we must not return to the + * caller which will try to do udelay's etc... Instead, we wait -here- + * for the CPU to callin. + */ + for (i = 0; i < 100000 && !cpu_callin_map[nr]; ++i) { + for (j = 1; j < 10000; j++) + asm volatile("nop" : : : "memory"); + asm volatile("sync" : : : "memory"); + } + if (!cpu_callin_map[nr]) + goto stuck; + + /* And we do the TB sync here too for standard dual CPU cards */ + if (psurge_type == PSURGE_DUAL) { + while(!tb_req) + barrier(); + tb_req = 0; + mb(); + timebase = get_tb(); + mb(); + while (timebase) + barrier(); mb(); - sec_tb_reset = 1; - return; } + stuck: + /* now interrupt the secondary, restarting both TBs */ + if (psurge_type == PSURGE_DUAL) + psurge_set_ipi(1); - /* wait for the secondary to have reset its TB before proceeding */ - for (t = 10000000; t > 0 && !sec_tb_reset; --t) - ; - - /* now interrupt the secondary, starting both TBs */ - psurge_set_ipi(1); + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); } static struct irqaction psurge_irqaction = { @@ -390,36 +402,35 @@ static struct irqaction psurge_irqaction = { static void __init smp_psurge_setup_cpu(int cpu_nr) { + if (cpu_nr != 0) + return; - if (cpu_nr == 0) { - /* If we failed to start the second CPU, we should still - * send it an IPI to start the timebase & DEC or we might - * have them stuck. - */ - if (num_online_cpus() < 2) { - if (psurge_type == PSURGE_DUAL) - psurge_set_ipi(1); - return; - } - /* reset the entry point so if we get another intr we won't - * try to startup again */ - out_be32(psurge_start, 0x100); - if (setup_irq(30, &psurge_irqaction)) - printk(KERN_ERR "Couldn't get primary IPI interrupt"); - } - - if (psurge_type == PSURGE_DUAL) - psurge_dual_sync_tb(cpu_nr); + /* reset the entry point so if we get another intr we won't + * try to startup again */ + out_be32(psurge_start, 0x100); + if (setup_irq(30, &psurge_irqaction)) + printk(KERN_ERR "Couldn't get primary IPI interrupt"); } void __init smp_psurge_take_timebase(void) { - /* Dummy implementation */ + if (psurge_type != PSURGE_DUAL) + return; + + tb_req = 1; + mb(); + while (!timebase) + barrier(); + mb(); + set_tb(timebase >> 32, timebase & 0xffffffff); + timebase = 0; + mb(); + set_dec(tb_ticks_per_jiffy/2); } void __init smp_psurge_give_timebase(void) { - /* Dummy implementation */ + /* Nothing to do here */ } /* PowerSurge-style Macs */ @@ -437,9 +448,6 @@ struct smp_ops_t psurge_smp_ops = { * Core 99 and later support */ -static void (*pmac_tb_freeze)(int freeze); -static u64 timebase; -static int tb_req; static void smp_core99_give_timebase(void) { @@ -478,7 +486,6 @@ static void __devinit smp_core99_take_timebase(void) set_tb(timebase >> 32, timebase & 0xffffffff); timebase = 0; mb(); - set_dec(tb_ticks_per_jiffy/2); local_irq_restore(flags); } @@ -920,3 +927,34 @@ struct smp_ops_t core99_smp_ops = { # endif #endif }; + +void __init pmac_setup_smp(void) +{ + struct device_node *np; + + /* Check for Core99 */ + np = of_find_node_by_name(NULL, "uni-n"); + if (!np) + np = of_find_node_by_name(NULL, "u3"); + if (!np) + np = of_find_node_by_name(NULL, "u4"); + if (np) { + of_node_put(np); + smp_ops = &core99_smp_ops; + } +#ifdef CONFIG_PPC32 + else { + /* We have to set bits in cpu_possible_map here since the + * secondary CPU(s) aren't in the device tree. Various + * things won't be initialized for CPUs not in the possible + * map, so we really need to fix it up here. + */ + int cpu; + + for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu) + cpu_set(cpu, cpu_possible_map); + smp_ops = &psurge_smp_ops; + } +#endif /* CONFIG_PPC32 */ +} + -- GitLab From a2367194183d6ab6b05e5d7d9b40db6ba48afc06 Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Thu, 18 Jun 2009 22:29:55 +0000 Subject: [PATCH 0232/1002] powerpc: Fix output from show_regs For some reason we've had an explicit KERN_INFO for GPR dumps. With recent changes we get output like: <6>GPR00: 00000000 ef855eb0 ef858000 00000001 000000d0 f1000000 ffbc8000 ffffffff The KERN_INFO is causing the <6>. Don't see any reason to keep it around. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3e7135bbe40f6..892a9f2e6d76a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -528,7 +528,7 @@ void show_regs(struct pt_regs * regs) for (i = 0; i < 32; i++) { if ((i % REGS_PER_LINE) == 0) - printk("\n" KERN_INFO "GPR%02d: ", i); + printk("\nGPR%02d: ", i); printk(REG " ", regs->gpr[i]); if (i == LAST_VOLATILE && !FULL_REGS(regs)) break; -- GitLab From 85355bb272db31a3f2dd99d547eef794805e1319 Mon Sep 17 00:00:00 2001 From: Kumar Gala <galak@kernel.crashing.org> Date: Thu, 18 Jun 2009 22:01:20 +0000 Subject: [PATCH 0233/1002] powerpc: Fix mpic alloc warning Since we can use kmalloc earlier we are getting the following since the mpic_alloc() code calls alloc_bootmem(). Move to using kzalloc() to remove the warning. ------------[ cut here ]------------ Badness at c0583248 [verbose debug info unavailable] NIP: c0583248 LR: c0583210 CTR: 00000004 REGS: c0741de0 TRAP: 0700 Not tainted (2.6.30-06736-g12a31df) MSR: 00021000 <ME,CE> CR: 22024024 XER: 00000000 TASK = c070d3b8[0] 'swapper' THREAD: c0740000 CPU: 0 <6>GPR00: 00000001 c0741e90 c070d3b8 00000001 00000210 00000020 3fffffff 00000000 <6>GPR08: 00000000 c0c85700 c04f8c40 0000002d 22044022 1004a388 7ffd9400 00000000 <6>GPR16: 00000000 7ffcd100 7ffcd100 7ffcd100 c04f8c40 00000000 c059f62c c075a0c0 <6>GPR24: c059f648 00000000 0000000f 00000210 00000020 00000000 3fffffff 00000210 NIP [c0583248] alloc_arch_preferred_bootmem+0x50/0x80 LR [c0583210] alloc_arch_preferred_bootmem+0x18/0x80 Call Trace: [c0741e90] [c07343b0] devtree_lock+0x0/0x24 (unreliable) [c0741ea0] [c0583b14] ___alloc_bootmem_nopanic+0x54/0x108 [c0741ee0] [c0583e18] ___alloc_bootmem+0x18/0x50 [c0741ef0] [c057b9cc] mpic_alloc+0x48/0x710 [c0741f40] [c057ecf4] mpc85xx_ds_pic_init+0x190/0x1b8 [c0741f90] [c057633c] init_IRQ+0x24/0x34 [c0741fa0] [c05738b8] start_kernel+0x260/0x3dc [c0741ff0] [c00003c8] skpinv+0x2e0/0x31c Instruction dump: 409e001c 7c030378 80010014 83e1000c 38210010 7c0803a6 4e800020 3d20c0c8 39295700 80090004 7c000034 5400d97e <0f000000> 2f800000 409e001c 38800000 BenH: Changed to use GFP_KERNEL, the allocator will do the right thing Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/sysdev/mpic.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 32a2e950f5638..d46de1f0f3eed 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1053,11 +1053,10 @@ struct mpic * __init mpic_alloc(struct device_node *node, int intvec_top; u64 paddr = phys_addr; - mpic = alloc_bootmem(sizeof(struct mpic)); + mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); if (mpic == NULL) return NULL; - - memset(mpic, 0, sizeof(struct mpic)); + mpic->name = name; mpic->hc_irq = mpic_irq_chip; -- GitLab From 850f6ac316cf84bba63fdb775c897834eccbfaa3 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Thu, 18 Jun 2009 19:25:00 +0000 Subject: [PATCH 0234/1002] powerpc/mm: Make k(un)map_atomic out of line Those functions are way too big to be inline, besides, kmap_atomic() wants to call debug_kmap_atomic() which isn't exported for modules and causes module link failures. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/highmem.h | 57 ++-------------------- arch/powerpc/mm/Makefile | 1 + arch/powerpc/mm/highmem.c | 77 ++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 53 deletions(-) create mode 100644 arch/powerpc/mm/highmem.c diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h index 684a73f4324f4..a74c4ee6c0205 100644 --- a/arch/powerpc/include/asm/highmem.h +++ b/arch/powerpc/include/asm/highmem.h @@ -22,9 +22,7 @@ #ifdef __KERNEL__ -#include <linux/init.h> #include <linux/interrupt.h> -#include <linux/highmem.h> #include <asm/kmap_types.h> #include <asm/tlbflush.h> #include <asm/page.h> @@ -62,6 +60,9 @@ extern pte_t *pkmap_page_table; extern void *kmap_high(struct page *page); extern void kunmap_high(struct page *page); +extern void *kmap_atomic_prot(struct page *page, enum km_type type, + pgprot_t prot); +extern void kunmap_atomic(void *kvaddr, enum km_type type); static inline void *kmap(struct page *page) { @@ -79,62 +80,11 @@ static inline void kunmap(struct page *page) kunmap_high(page); } -/* - * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap - * gives a more generic (and caching) interface. But kmap_atomic can - * be used in IRQ contexts, so in some (very limited) cases we need - * it. - */ -static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) -{ - unsigned int idx; - unsigned long vaddr; - - /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - pagefault_disable(); - if (!PageHighMem(page)) - return page_address(page); - - debug_kmap_atomic(type); - idx = type + KM_TYPE_NR*smp_processor_id(); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -#ifdef CONFIG_DEBUG_HIGHMEM - BUG_ON(!pte_none(*(kmap_pte-idx))); -#endif - __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1); - local_flush_tlb_page(NULL, vaddr); - - return (void*) vaddr; -} - static inline void *kmap_atomic(struct page *page, enum km_type type) { return kmap_atomic_prot(page, type, kmap_prot); } -static inline void kunmap_atomic(void *kvaddr, enum km_type type) -{ -#ifdef CONFIG_DEBUG_HIGHMEM - unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; - enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); - - if (vaddr < __fix_to_virt(FIX_KMAP_END)) { - pagefault_enable(); - return; - } - - BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); - - /* - * force other mappings to Oops if they'll try to access - * this pte without first remap it - */ - pte_clear(&init_mm, vaddr, kmap_pte-idx); - local_flush_tlb_page(NULL, vaddr); -#endif - pagefault_enable(); -} - static inline struct page *kmap_atomic_to_page(void *ptr) { unsigned long idx, vaddr = (unsigned long) ptr; @@ -148,6 +98,7 @@ static inline struct page *kmap_atomic_to_page(void *ptr) return pte_page(*pte); } + #define flush_cache_kmaps() flush_cache_all() #endif /* __KERNEL__ */ diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 2d2192e48de73..3e68363405b79 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_PPC_MM_SLICES) += slice.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o +obj-$(CONFIG_HIGHMEM) += highmem.o diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c new file mode 100644 index 0000000000000..c2186c74c85a8 --- /dev/null +++ b/arch/powerpc/mm/highmem.c @@ -0,0 +1,77 @@ +/* + * highmem.c: virtual kernel memory mappings for high memory + * + * PowerPC version, stolen from the i386 version. + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual addresses. + * + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * + * + * Redesigned the x86 32-bit VM architecture to deal with + * up to 16 Terrabyte physical memory. With current x86 CPUs + * we now support up to 64 Gigabytes physical RAM. + * + * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> + * + * Reworked for PowerPC by various contributors. Moved from + * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp. + */ + +#include <linux/highmem.h> +#include <linux/module.h> + +/* + * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap + * gives a more generic (and caching) interface. But kmap_atomic can + * be used in IRQ contexts, so in some (very limited) cases we need + * it. + */ +void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) +{ + unsigned int idx; + unsigned long vaddr; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + pagefault_disable(); + if (!PageHighMem(page)) + return page_address(page); + + debug_kmap_atomic(type); + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + BUG_ON(!pte_none(*(kmap_pte-idx))); +#endif + __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1); + local_flush_tlb_page(NULL, vaddr); + + return (void*) vaddr; +} +EXPORT_SYMBOL(kmap_atomic_prot); + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ +#ifdef CONFIG_DEBUG_HIGHMEM + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < __fix_to_virt(FIX_KMAP_END)) { + pagefault_enable(); + return; + } + + BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(&init_mm, vaddr, kmap_pte-idx); + local_flush_tlb_page(NULL, vaddr); +#endif + pagefault_enable(); +} +EXPORT_SYMBOL(kunmap_atomic); -- GitLab From 3514141aedc16c7344117d5bd79ec1310edf8fb3 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Thu, 18 Jun 2009 19:20:51 +0000 Subject: [PATCH 0235/1002] powerpc/pmac: Fix DMA ops for MacIO devices The macio_dev's created to map devices inside the MacIO ASICs don't have proper dma_ops. This causes crashes on some machines since the SCSI code calls dma_map_* on our behalf using the device we hang from. This fixes it by copying the parent PCI device dma_ops into the macio_dev when creating it. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- drivers/macintosh/macio_asic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 6e149f4a1fff6..a0f68386c12f3 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -378,6 +378,17 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, dev->ofdev.dev.bus = &macio_bus_type; dev->ofdev.dev.release = macio_release_dev; +#ifdef CONFIG_PCI + /* Set the DMA ops to the ones from the PCI device, this could be + * fishy if we didn't know that on PowerMac it's always direct ops + * or iommu ops that will work fine + */ + dev->ofdev.dev.archdata.dma_ops = + chip->lbus.pdev->dev.archdata.dma_ops; + dev->ofdev.dev.archdata.dma_data = + chip->lbus.pdev->dev.archdata.dma_data; +#endif /* CONFIG_PCI */ + #ifdef DEBUG printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); -- GitLab From 4a5cbf17c49a6024a6d7baf03efdffb8ed252bb1 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Thu, 18 Jun 2009 19:17:39 +0000 Subject: [PATCH 0236/1002] powerpc: Map more memory early on 601 processors The 32-bit kernel relies on some memory being mapped covering the kernel text,data and bss at least, early during boot before the full MMU setup is done. On 32-bit "classic" processors, this is done using BAT registers. On 601, the size of BATs is limited to 8M and we use 2 of them for that initial mapping. This can become quite tight when enabling features like lockdep, so let's use a 3rd one to bump that mapping from 16M to 24M. We keep the 4th BAT free as it can be useful for debugging early boot code to map things like serial ports. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/head_32.S | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 48469463f89e7..fc2132942754e 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -1124,9 +1124,8 @@ mmu_off: RFI /* - * Use the first pair of BAT registers to map the 1st 16MB - * of RAM to PAGE_OFFSET. From this point on we can't safely - * call OF any more. + * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET + * (we keep one for debugging) and on others, we use one 256M BAT. */ initial_bats: lis r11,PAGE_OFFSET@h @@ -1136,12 +1135,16 @@ initial_bats: bne 4f ori r11,r11,4 /* set up BAT registers for 601 */ li r8,0x7f /* valid, block length = 8MB */ - oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ - oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */ mtspr SPRN_IBAT0L,r8 /* lower BAT register */ - mtspr SPRN_IBAT1U,r9 - mtspr SPRN_IBAT1L,r10 + addis r11,r11,0x800000@h + addis r8,r8,0x800000@h + mtspr SPRN_IBAT1U,r11 + mtspr SPRN_IBAT1L,r8 + addis r11,r11,0x800000@h + addis r8,r8,0x800000@h + mtspr SPRN_IBAT2U,r11 + mtspr SPRN_IBAT2L,r8 isync blr -- GitLab From e4031d52c57b17c76bbdb15fcf1a32a9f87d9756 Mon Sep 17 00:00:00 2001 From: Sonny Rao <sonnyrao@us.ibm.com> Date: Thu, 18 Jun 2009 15:14:36 +0000 Subject: [PATCH 0237/1002] powerpc/BSR: add 4096 byte BSR size Add a 4096 byte BSR size which will be used on new machines. Also, remove the warning when we run into an unknown size, as this can spam the kernel log excessively. Signed-off-by: Sonny Rao <sonnyrao@us.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- drivers/char/bsr.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 140ea10ecb886..7d9fd8a8dfd05 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -75,12 +75,13 @@ static struct class *bsr_class; static int bsr_major; enum { - BSR_8 = 0, - BSR_16 = 1, - BSR_64 = 2, - BSR_128 = 3, - BSR_UNKNOWN = 4, - BSR_MAX = 5, + BSR_8 = 0, + BSR_16 = 1, + BSR_64 = 2, + BSR_128 = 3, + BSR_4096 = 4, + BSR_UNKNOWN = 5, + BSR_MAX = 6, }; static unsigned bsr_types[BSR_MAX]; @@ -218,9 +219,11 @@ static int bsr_add_node(struct device_node *bn) case 128: cur->bsr_type = BSR_128; break; + case 4096: + cur->bsr_type = BSR_4096; + break; default: cur->bsr_type = BSR_UNKNOWN; - printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes); } cur->bsr_num = bsr_types[cur->bsr_type]; -- GitLab From 04a85d1234d7e1682a612565e663e6b760918643 Mon Sep 17 00:00:00 2001 From: Sonny Rao <sonnyrao@us.ibm.com> Date: Thu, 18 Jun 2009 15:13:04 +0000 Subject: [PATCH 0238/1002] powerpc/BSR: Fix BSR to allow mmap of small BSR on 64k kernel On Mon, Nov 17, 2008 at 01:26:13AM -0600, Sonny Rao wrote: > On Fri, Nov 07, 2008 at 04:28:29PM +1100, Paul Mackerras wrote: > > Sonny Rao writes: > > > > > Fix the BSR driver to allow small BSR devices, which are limited to a > > > single 4k space, on a 64k page kernel. Previously the driver would > > > reject the mmap since the size was smaller than PAGESIZE (or because > > > the size was greater than the size of the device). Now, we check for > > > this case use remap_4k_pfn(). Also, take out code to set vm_flags, > > > as the remap_pfn functions will do this for us. > > > > Thanks. > > > > Do we know that the BSR size will always be 4k if it's not a multiple > > of 64k? Is it possible that we could get 8k, 16k or 32k or BSRs? > > If it is possible, what does the user need to be able to do? Do they > > just want to map 4k, or might then want to map the whole thing? > > > Hi Paul, I took a look at changing the driver to reject a request for > mapping more than a single 4k page, however the only indication we get > of the requested size in the mmap function is the vma size, and this > is always one page at minimum. So, it's not possible to determine if > the user wants one 4k page or more. As I noted in my first response, > there is only one case where this is even possible and I don't think > it is a significant concern. > > I did notice that I left out the check to see if the user is trying to > map more than the device length, so I fixed that. Here's the revised > patch. Alright, I've reworked this now so that if we get one of these cases where there's a bsr that's > 4k and < 64k on a 64k kernel we'll only advertise that it is a 4k BSR to userspace. I think this is the best solution since user programs are only supposed to look at sysfs to determine how much can be mapped, and libbsr does this as well. Please consider for 2.6.31 as a fix, thanks. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- drivers/char/bsr.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 7d9fd8a8dfd05..c02db01f736ea 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -27,6 +27,7 @@ #include <linux/cdev.h> #include <linux/list.h> #include <linux/mm.h> +#include <asm/pgtable.h> #include <asm/io.h> /* @@ -118,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; struct bsr_dev *dev = filp->private_data; + int ret; - if (size > dev->bsr_len || (size & (PAGE_SIZE-1))) - return -EINVAL; - - vma->vm_flags |= (VM_IO | VM_DONTEXPAND); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT, - size, vma->vm_page_prot)) + /* check for the case of a small BSR device and map one 4k page for it*/ + if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE) + ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12, + vma->vm_page_prot); + else if (size <= dev->bsr_len) + ret = io_remap_pfn_range(vma, vma->vm_start, + dev->bsr_addr >> PAGE_SHIFT, + size, vma->vm_page_prot); + else + return -EINVAL; + + if (ret) return -EAGAIN; return 0; @@ -206,6 +214,11 @@ static int bsr_add_node(struct device_node *bn) cur->bsr_stride = bsr_stride[i]; cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); + /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */ + /* we can only map 4k of it, so only advertise the 4k in sysfs */ + if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE) + cur->bsr_len = 4096; + switch(cur->bsr_bytes) { case 8: cur->bsr_type = BSR_8; -- GitLab From 5d38902c483881645ba16058cffaa478b81e5cfa Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Wed, 17 Jun 2009 17:43:59 +0000 Subject: [PATCH 0239/1002] powerpc: Add irqtrace support for 32-bit powerpc Based on initial work from: Dale Farnsworth <dale@farnsworth.org> Add the low level irq tracing hooks for 32-bit powerpc needed to enable full lockdep functionality. The approach taken to deal with the code in entry_32.S is that we don't trace all the transitions of MSR:EE when we just turn it off to peek at TI_FLAGS without races. Only when we are calling into C code or returning from exceptions with a state that have changed from what lockdep thinks. There's a little bugger though: If we take an exception that keeps interrupts enabled (such as an alignment exception) while interrupts are enabled, we will call trace_hardirqs_on() on the way back spurriously. Not a big deal, but to get rid of it would require remembering in pt_regs that the exception was one of the type that kept interrupts enabled which we don't know at this stage. (Well, we could test all cases for regs->trap but that sucks too much). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Tested-by: Kumar Gala <galak@kernel.crashing.org> --- arch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/hw_irq.h | 20 ++--- arch/powerpc/kernel/entry_32.S | 127 +++++++++++++++++++++++++++++- arch/powerpc/kernel/setup_32.c | 2 + 4 files changed, 135 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index bf6cedfa05dbf..d00131ca0835e 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -62,7 +62,6 @@ config HAVE_LATENCYTOP_SUPPORT config TRACE_IRQFLAGS_SUPPORT bool - depends on PPC64 default y config LOCKDEP_SUPPORT diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 867ab8ed69b30..8b505eaaa38a1 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -68,13 +68,13 @@ static inline int irqs_disabled_flags(unsigned long flags) #if defined(CONFIG_BOOKE) #define SET_MSR_EE(x) mtmsr(x) -#define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") +#define raw_local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") #else #define SET_MSR_EE(x) mtmsr(x) -#define local_irq_restore(flags) mtmsr(flags) +#define raw_local_irq_restore(flags) mtmsr(flags) #endif -static inline void local_irq_disable(void) +static inline void raw_local_irq_disable(void) { #ifdef CONFIG_BOOKE __asm__ __volatile__("wrteei 0": : :"memory"); @@ -86,7 +86,7 @@ static inline void local_irq_disable(void) #endif } -static inline void local_irq_enable(void) +static inline void raw_local_irq_enable(void) { #ifdef CONFIG_BOOKE __asm__ __volatile__("wrteei 1": : :"memory"); @@ -98,7 +98,7 @@ static inline void local_irq_enable(void) #endif } -static inline void local_irq_save_ptr(unsigned long *flags) +static inline void raw_local_irq_save_ptr(unsigned long *flags) { unsigned long msr; msr = mfmsr(); @@ -110,12 +110,12 @@ static inline void local_irq_save_ptr(unsigned long *flags) #endif } -#define local_save_flags(flags) ((flags) = mfmsr()) -#define local_irq_save(flags) local_irq_save_ptr(&flags) -#define irqs_disabled() ((mfmsr() & MSR_EE) == 0) +#define raw_local_save_flags(flags) ((flags) = mfmsr()) +#define raw_local_irq_save(flags) raw_local_irq_save_ptr(&flags) +#define raw_irqs_disabled() ((mfmsr() & MSR_EE) == 0) +#define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0) -#define hard_irq_enable() local_irq_enable() -#define hard_irq_disable() local_irq_disable() +#define hard_irq_disable() raw_local_irq_disable() static inline int irqs_disabled_flags(unsigned long flags) { diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4dd38f129153f..3cadba60a4b6c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -191,11 +191,49 @@ transfer_to_handler_cont: mflr r9 lwz r11,0(r9) /* virtual address of handler */ lwz r9,4(r9) /* where to go when done */ +#ifdef CONFIG_TRACE_IRQFLAGS + lis r12,reenable_mmu@h + ori r12,r12,reenable_mmu@l + mtspr SPRN_SRR0,r12 + mtspr SPRN_SRR1,r10 + SYNC + RFI +reenable_mmu: /* re-enable mmu so we can */ + mfmsr r10 + lwz r12,_MSR(r1) + xor r10,r10,r12 + andi. r10,r10,MSR_EE /* Did EE change? */ + beq 1f + + /* Save handler and return address into the 2 unused words + * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything + * else can be recovered from the pt_regs except r3 which for + * normal interrupts has been set to pt_regs and for syscalls + * is an argument, so we temporarily use ORIG_GPR3 to save it + */ + stw r9,8(r1) + stw r11,12(r1) + stw r3,ORIG_GPR3(r1) + bl trace_hardirqs_off + lwz r0,GPR0(r1) + lwz r3,ORIG_GPR3(r1) + lwz r4,GPR4(r1) + lwz r5,GPR5(r1) + lwz r6,GPR6(r1) + lwz r7,GPR7(r1) + lwz r8,GPR8(r1) + lwz r9,8(r1) + lwz r11,12(r1) +1: mtctr r11 + mtlr r9 + bctr /* jump to handler */ +#else /* CONFIG_TRACE_IRQFLAGS */ mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r10 mtlr r9 SYNC RFI /* jump to handler, enable MMU */ +#endif /* CONFIG_TRACE_IRQFLAGS */ #if defined (CONFIG_6xx) || defined(CONFIG_E500) 4: rlwinm r12,r12,0,~_TLF_NAPPING @@ -251,6 +289,31 @@ _GLOBAL(DoSyscall) #ifdef SHOW_SYSCALLS bl do_show_syscall #endif /* SHOW_SYSCALLS */ +#ifdef CONFIG_TRACE_IRQFLAGS + /* Return from syscalls can (and generally will) hard enable + * interrupts. You aren't supposed to call a syscall with + * interrupts disabled in the first place. However, to ensure + * that we get it right vs. lockdep if it happens, we force + * that hard enable here with appropriate tracing if we see + * that we have been called with interrupts off + */ + mfmsr r11 + andi. r12,r11,MSR_EE + bne+ 1f + /* We came in with interrupts disabled, we enable them now */ + bl trace_hardirqs_on + mfmsr r11 + lwz r0,GPR0(r1) + lwz r3,GPR3(r1) + lwz r4,GPR4(r1) + ori r11,r11,MSR_EE + lwz r5,GPR5(r1) + lwz r6,GPR6(r1) + lwz r7,GPR7(r1) + lwz r8,GPR8(r1) + mtmsr r11 +1: +#endif /* CONFIG_TRACE_IRQFLAGS */ rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ lwz r11,TI_FLAGS(r10) andi. r11,r11,_TIF_SYSCALL_T_OR_A @@ -275,6 +338,7 @@ ret_from_syscall: rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ /* disable interrupts so current_thread_info()->flags can't change */ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ + /* Note: We don't bother telling lockdep about it */ SYNC MTMSRD(r10) lwz r9,TI_FLAGS(r12) @@ -288,6 +352,19 @@ ret_from_syscall: oris r11,r11,0x1000 /* Set SO bit in CR */ stw r11,_CCR(r1) syscall_exit_cont: + lwz r8,_MSR(r1) +#ifdef CONFIG_TRACE_IRQFLAGS + /* If we are going to return from the syscall with interrupts + * off, we trace that here. It shouldn't happen though but we + * want to catch the bugger if it does right ? + */ + andi. r10,r8,MSR_EE + bne+ 1f + stw r3,GPR3(r1) + bl trace_hardirqs_off + lwz r3,GPR3(r1) +1: +#endif /* CONFIG_TRACE_IRQFLAGS */ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) /* If the process has its own DBCR0 value, load it up. The internal debug mode bit tells us that dbcr0 should be loaded. */ @@ -311,7 +388,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) mtlr r4 mtcr r5 lwz r7,_NIP(r1) - lwz r8,_MSR(r1) FIX_SRR1(r8, r0) lwz r2,GPR2(r1) lwz r1,GPR1(r1) @@ -394,7 +470,9 @@ syscall_exit_work: andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) beq ret_from_except - /* Re-enable interrupts */ + /* Re-enable interrupts. There is no need to trace that with + * lockdep as we are supposed to have IRQs on at this point + */ ori r10,r10,MSR_EE SYNC MTMSRD(r10) @@ -705,6 +783,7 @@ ret_from_except: /* Hard-disable interrupts so that current_thread_info()->flags * can't change between when we test it and when we return * from the interrupt. */ + /* Note: We don't bother telling lockdep about it */ LOAD_MSR_KERNEL(r10,MSR_KERNEL) SYNC /* Some chip revs have problems here... */ MTMSRD(r10) /* disable interrupts */ @@ -744,11 +823,24 @@ resume_kernel: beq+ restore andi. r0,r3,MSR_EE /* interrupts off? */ beq restore /* don't schedule if so */ +#ifdef CONFIG_TRACE_IRQFLAGS + /* Lockdep thinks irqs are enabled, we need to call + * preempt_schedule_irq with IRQs off, so we inform lockdep + * now that we -did- turn them off already + */ + bl trace_hardirqs_off +#endif 1: bl preempt_schedule_irq rlwinm r9,r1,0,0,(31-THREAD_SHIFT) lwz r3,TI_FLAGS(r9) andi. r0,r3,_TIF_NEED_RESCHED bne- 1b +#ifdef CONFIG_TRACE_IRQFLAGS + /* And now, to properly rebalance the above, we tell lockdep they + * are being turned back on, which will happen when we return + */ + bl trace_hardirqs_on +#endif #else resume_kernel: #endif /* CONFIG_PREEMPT */ @@ -765,6 +857,28 @@ restore: stw r6,icache_44x_need_flush@l(r4) 1: #endif /* CONFIG_44x */ + + lwz r9,_MSR(r1) +#ifdef CONFIG_TRACE_IRQFLAGS + /* Lockdep doesn't know about the fact that IRQs are temporarily turned + * off in this assembly code while peeking at TI_FLAGS() and such. However + * we need to inform it if the exception turned interrupts off, and we + * are about to trun them back on. + * + * The problem here sadly is that we don't know whether the exceptions was + * one that turned interrupts off or not. So we always tell lockdep about + * turning them on here when we go back to wherever we came from with EE + * on, even if that may meen some redudant calls being tracked. Maybe later + * we could encode what the exception did somewhere or test the exception + * type in the pt_regs but that sounds overkill + */ + andi. r10,r9,MSR_EE + beq 1f + bl trace_hardirqs_on + lwz r9,_MSR(r1) +1: +#endif /* CONFIG_TRACE_IRQFLAGS */ + lwz r0,GPR0(r1) lwz r2,GPR2(r1) REST_4GPRS(3, r1) @@ -782,7 +896,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) - lwz r9,_MSR(r1) andi. r10,r9,MSR_RI /* check if this exception occurred */ beql nonrecoverable /* at a bad place (MSR:RI = 0) */ @@ -805,7 +918,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) MTMSRD(r10) /* clear the RI bit */ .globl exc_exit_restart exc_exit_restart: - lwz r9,_MSR(r1) lwz r12,_NIP(r1) FIX_SRR1(r9,r10) mtspr SPRN_SRR0,r12 @@ -1035,11 +1147,18 @@ do_work: /* r10 contains MSR_KERNEL here */ beq do_user_signal do_resched: /* r10 contains MSR_KERNEL here */ + /* Note: We don't need to inform lockdep that we are enabling + * interrupts here. As far as it knows, they are already enabled + */ ori r10,r10,MSR_EE SYNC MTMSRD(r10) /* hard-enable interrupts */ bl schedule recheck: + /* Note: And we don't tell it we are disabling them again + * neither. Those disable/enable cycles used to peek at + * TI_FLAGS aren't advertised. + */ LOAD_MSR_KERNEL(r10,MSR_KERNEL) SYNC MTMSRD(r10) /* disable interrupts */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 1d154248cf40e..e1e3059cf34b9 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -119,6 +119,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr) */ notrace void __init machine_init(unsigned long dt_ptr) { + lockdep_init(); + /* Enable early debugging if any specified (see udbg.h) */ udbg_early_init(); -- GitLab From f97bb36f705da0a86b3ea77bfeee3415fee0b025 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Tue, 16 Jun 2009 16:42:49 +0000 Subject: [PATCH 0240/1002] powerpc/rtas: Turn rtas lock into a raw spinlock RTAS currently uses a normal spinlock. However it can be called from contexts where this is not necessarily a good idea. For example, it can be called while syncing timebases, with the core timebase being frozen. Unfortunately, that will deadlock in case of lock contention when spinlock debugging is enabled as the spin lock debugging code will try to use __delay() which ... relies on the timebase being enabled. Also RTAS can be used in some low level IRQ handling code path so it may as well be a raw spinlock for -rt sake. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/rtas.h | 2 +- arch/powerpc/kernel/rtas.c | 38 +++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 01c12339b3044..0af42d20b692a 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -58,7 +58,7 @@ struct rtas_t { unsigned long entry; /* physical address pointer */ unsigned long base; /* physical address pointer */ unsigned long size; - spinlock_t lock; + raw_spinlock_t lock; struct rtas_args args; struct device_node *dev; /* virtual address pointer */ }; diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index ee4c7609b649e..d9a9974c69389 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -40,7 +40,7 @@ #include <asm/atomic.h> struct rtas_t rtas = { - .lock = SPIN_LOCK_UNLOCKED + .lock = __RAW_SPIN_LOCK_UNLOCKED }; EXPORT_SYMBOL(rtas); @@ -67,6 +67,28 @@ unsigned long rtas_rmo_buf; void (*rtas_flash_term_hook)(int); EXPORT_SYMBOL(rtas_flash_term_hook); +/* RTAS use home made raw locking instead of spin_lock_irqsave + * because those can be called from within really nasty contexts + * such as having the timebase stopped which would lockup with + * normal locks and spinlock debugging enabled + */ +static unsigned long lock_rtas(void) +{ + unsigned long flags; + + local_irq_save(flags); + preempt_disable(); + __raw_spin_lock_flags(&rtas.lock, flags); + return flags; +} + +static void unlock_rtas(unsigned long flags) +{ + __raw_spin_unlock(&rtas.lock); + local_irq_restore(flags); + preempt_enable(); +} + /* * call_rtas_display_status and call_rtas_display_status_delay * are designed only for very early low-level debugging, which @@ -79,7 +101,7 @@ static void call_rtas_display_status(char c) if (!rtas.base) return; - spin_lock_irqsave(&rtas.lock, s); + s = lock_rtas(); args->token = 10; args->nargs = 1; @@ -89,7 +111,7 @@ static void call_rtas_display_status(char c) enter_rtas(__pa(args)); - spin_unlock_irqrestore(&rtas.lock, s); + unlock_rtas(s); } static void call_rtas_display_status_delay(char c) @@ -411,8 +433,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) return -1; - /* Gotta do something different here, use global lock for now... */ - spin_lock_irqsave(&rtas.lock, s); + s = lock_rtas(); rtas_args = &rtas.args; rtas_args->token = token; @@ -439,8 +460,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) outputs[i] = rtas_args->rets[i+1]; ret = (nret > 0)? rtas_args->rets[0]: 0; - /* Gotta do something different here, use global lock for now... */ - spin_unlock_irqrestore(&rtas.lock, s); + unlock_rtas(s); if (buff_copy) { log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); @@ -837,7 +857,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) buff_copy = get_errorlog_buffer(); - spin_lock_irqsave(&rtas.lock, flags); + flags = lock_rtas(); rtas.args = args; enter_rtas(__pa(&rtas.args)); @@ -848,7 +868,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) if (args.rets[0] == -1) errbuf = __fetch_rtas_last_error(buff_copy); - spin_unlock_irqrestore(&rtas.lock, flags); + unlock_rtas(flags); if (buff_copy) { if (errbuf) -- GitLab From c4007a2fbf5f82b7e694c22b5929c87e38415a56 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Tue, 16 Jun 2009 16:42:50 +0000 Subject: [PATCH 0241/1002] powerpc: Use one common impl. of RTAS timebase sync and use raw spinlock Several platforms use their own copy of what is essentially the same code, using RTAS to synchronize the timebases when bringing up new CPUs. This moves it all into a single common implementation and additionally turns the spinlock into a raw spinlock since the former can rely on the timebase not being frozen when spinlock debugging is enabled, and finally masks interrupts while the timebase is disabled. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/rtas.h | 3 +++ arch/powerpc/kernel/rtas.c | 31 ++++++++++++++++++++++++++ arch/powerpc/platforms/cell/smp.c | 30 ++----------------------- arch/powerpc/platforms/chrp/smp.c | 33 ++-------------------------- arch/powerpc/platforms/pseries/smp.c | 30 ++----------------------- 5 files changed, 40 insertions(+), 87 deletions(-) diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 0af42d20b692a..168fce726201d 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -245,5 +245,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg) (devfn << 8) | (reg & 0xff); } +extern void __cpuinit rtas_give_timebase(void); +extern void __cpuinit rtas_take_timebase(void); + #endif /* __KERNEL__ */ #endif /* _POWERPC_RTAS_H */ diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index d9a9974c69389..c434823b8c83a 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -38,6 +38,7 @@ #include <asm/syscalls.h> #include <asm/smp.h> #include <asm/atomic.h> +#include <asm/time.h> struct rtas_t rtas = { .lock = __RAW_SPIN_LOCK_UNLOCKED @@ -971,3 +972,33 @@ int __init early_init_dt_scan_rtas(unsigned long node, /* break now */ return 1; } + +static raw_spinlock_t timebase_lock; +static u64 timebase = 0; + +void __cpuinit rtas_give_timebase(void) +{ + unsigned long flags; + + local_irq_save(flags); + hard_irq_disable(); + __raw_spin_lock(&timebase_lock); + rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); + timebase = get_tb(); + __raw_spin_unlock(&timebase_lock); + + while (timebase) + barrier(); + rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); + local_irq_restore(flags); +} + +void __cpuinit rtas_take_timebase(void) +{ + while (!timebase) + barrier(); + __raw_spin_lock(&timebase_lock); + set_tb(timebase >> 32, timebase & 0xffffffff); + timebase = 0; + __raw_spin_unlock(&timebase_lock); +} diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index 9046803c82767..bc97fada48c66 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -36,7 +36,6 @@ #include <asm/prom.h> #include <asm/smp.h> #include <asm/paca.h> -#include <asm/time.h> #include <asm/machdep.h> #include <asm/cputable.h> #include <asm/firmware.h> @@ -140,31 +139,6 @@ static void __devinit smp_cell_setup_cpu(int cpu) mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER); } -static DEFINE_SPINLOCK(timebase_lock); -static unsigned long timebase = 0; - -static void __devinit cell_give_timebase(void) -{ - spin_lock(&timebase_lock); - rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); - timebase = get_tb(); - spin_unlock(&timebase_lock); - - while (timebase) - barrier(); - rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); -} - -static void __devinit cell_take_timebase(void) -{ - while (!timebase) - barrier(); - spin_lock(&timebase_lock); - set_tb(timebase >> 32, timebase & 0xffffffff); - timebase = 0; - spin_unlock(&timebase_lock); -} - static void __devinit smp_cell_kick_cpu(int nr) { BUG_ON(nr < 0 || nr >= NR_CPUS); @@ -224,8 +198,8 @@ void __init smp_init_cell(void) /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { - smp_ops->give_timebase = cell_give_timebase; - smp_ops->take_timebase = cell_take_timebase; + smp_ops->give_timebase = rtas_give_timebase; + smp_ops->take_timebase = rtas_take_timebase; } DBG(" <- smp_init_cell()\n"); diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index 10a4a4d063b64..02cafecc90e32 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c @@ -26,7 +26,6 @@ #include <asm/io.h> #include <asm/prom.h> #include <asm/smp.h> -#include <asm/time.h> #include <asm/machdep.h> #include <asm/mpic.h> #include <asm/rtas.h> @@ -42,40 +41,12 @@ static void __devinit smp_chrp_setup_cpu(int cpu_nr) mpic_setup_this_cpu(); } -static DEFINE_SPINLOCK(timebase_lock); -static unsigned int timebase_upper = 0, timebase_lower = 0; - -void __devinit smp_chrp_give_timebase(void) -{ - spin_lock(&timebase_lock); - rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); - timebase_upper = get_tbu(); - timebase_lower = get_tbl(); - spin_unlock(&timebase_lock); - - while (timebase_upper || timebase_lower) - barrier(); - rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); -} - -void __devinit smp_chrp_take_timebase(void) -{ - while (!(timebase_upper || timebase_lower)) - barrier(); - spin_lock(&timebase_lock); - set_tb(timebase_upper, timebase_lower); - timebase_upper = 0; - timebase_lower = 0; - spin_unlock(&timebase_lock); - printk("CPU %i taken timebase\n", smp_processor_id()); -} - /* CHRP with openpic */ struct smp_ops_t chrp_smp_ops = { .message_pass = smp_mpic_message_pass, .probe = smp_mpic_probe, .kick_cpu = smp_chrp_kick_cpu, .setup_cpu = smp_chrp_setup_cpu, - .give_timebase = smp_chrp_give_timebase, - .take_timebase = smp_chrp_take_timebase, + .give_timebase = rtas_give_timebase, + .take_timebase = rtas_take_timebase, }; diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 1a231c389ba01..1f8f6cfb94f7f 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -35,7 +35,6 @@ #include <asm/prom.h> #include <asm/smp.h> #include <asm/paca.h> -#include <asm/time.h> #include <asm/machdep.h> #include <asm/cputable.h> #include <asm/firmware.h> @@ -118,31 +117,6 @@ static void __devinit smp_xics_setup_cpu(int cpu) } #endif /* CONFIG_XICS */ -static DEFINE_SPINLOCK(timebase_lock); -static unsigned long timebase = 0; - -static void __devinit pSeries_give_timebase(void) -{ - spin_lock(&timebase_lock); - rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); - timebase = get_tb(); - spin_unlock(&timebase_lock); - - while (timebase) - barrier(); - rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); -} - -static void __devinit pSeries_take_timebase(void) -{ - while (!timebase) - barrier(); - spin_lock(&timebase_lock); - set_tb(timebase >> 32, timebase & 0xffffffff); - timebase = 0; - spin_unlock(&timebase_lock); -} - static void __devinit smp_pSeries_kick_cpu(int nr) { BUG_ON(nr < 0 || nr >= NR_CPUS); @@ -209,8 +183,8 @@ static void __init smp_init_pseries(void) /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { - smp_ops->give_timebase = pSeries_give_timebase; - smp_ops->take_timebase = pSeries_take_timebase; + smp_ops->give_timebase = rtas_give_timebase; + smp_ops->take_timebase = rtas_take_timebase; } pr_debug(" <- smp_init_pSeries()\n"); -- GitLab From 6893ce6c1cdcf489b7ca8e6b6596208aa971a083 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Tue, 16 Jun 2009 16:42:51 +0000 Subject: [PATCH 0242/1002] powerpc/pasemi: Use raw spinlock in SMP TB sync spin_lock() can hang if called while the timebase is frozen, so use a raw lock instead, also disable interrupts while at it. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/pasemi/setup.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 153051eb6d933..a4619347aa7e6 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -71,20 +71,25 @@ static void pas_restart(char *cmd) } #ifdef CONFIG_SMP -static DEFINE_SPINLOCK(timebase_lock); +static raw_spinlock_t timebase_lock; static unsigned long timebase; static void __devinit pas_give_timebase(void) { - spin_lock(&timebase_lock); + unsigned long flags; + + local_irq_save(flags); + hard_irq_disable(); + __raw_spin_lock(&timebase_lock); mtspr(SPRN_TBCTL, TBCTL_FREEZE); isync(); timebase = get_tb(); - spin_unlock(&timebase_lock); + __raw_spin_unlock(&timebase_lock); while (timebase) barrier(); mtspr(SPRN_TBCTL, TBCTL_RESTART); + local_irq_restore(flags); } static void __devinit pas_take_timebase(void) @@ -92,10 +97,10 @@ static void __devinit pas_take_timebase(void) while (!timebase) smp_rmb(); - spin_lock(&timebase_lock); + __raw_spin_lock(&timebase_lock); set_tb(timebase >> 32, timebase & 0xffffffff); timebase = 0; - spin_unlock(&timebase_lock); + __raw_spin_unlock(&timebase_lock); } struct smp_ops_t pas_smp_ops = { -- GitLab From 03c01aa740d4137ea2884328f2c29956c6084834 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Tue, 16 Jun 2009 15:55:18 +0000 Subject: [PATCH 0243/1002] powerpc/of: Fix usage of dev_set_name() in of_device_alloc() dev_set_name() takes a format string, so use it properly and avoid a warning with recent gcc's Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/of_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index fa983a59c4ce1..a359cb08e9006 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -76,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np, dev->dev.archdata.of_node = np; if (bus_id) - dev_set_name(&dev->dev, bus_id); + dev_set_name(&dev->dev, "%s", bus_id); else of_device_make_bus_id(dev); -- GitLab From f694cda89250f38782a5fd0b2d32fe33a39dcf37 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Tue, 16 Jun 2009 15:55:19 +0000 Subject: [PATCH 0244/1002] powerpc/440: Fix warning early debug code The function udbg_44x_as1_flush() has the wrong prototype causing a warning when enabling 440 early debug. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/udbg_16550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 0362a891e54ee..acb74a17bbbfa 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -219,7 +219,7 @@ void udbg_init_pas_realmode(void) #ifdef CONFIG_PPC_EARLY_DEBUG_44x #include <platforms/44x/44x.h> -static int udbg_44x_as1_flush(void) +static void udbg_44x_as1_flush(void) { if (udbg_comport) { while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) -- GitLab From 6c16a74d423f584ed80815ee7b944f5b578dd37a Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: Mon, 15 Jun 2009 16:53:43 +0000 Subject: [PATCH 0245/1002] powerpc/mm: Fix potential access to freed pages when using hugetlbfs When using 64k page sizes, our PTE pages are split in two halves, the second half containing the "extension" used to keep track of individual 4k pages when not using HW 64k pages. However, our page tables used for hugetlb have a slightly different format and don't carry that "second half". Our code that batched PTEs to be invalidated unconditionally reads the "second half" (to put it into the batch), which means that when called to invalidate hugetlb PTEs, it will access unrelated memory. It breaks when CONFIG_DEBUG_PAGEALLOC is enabled. This fixes it by only accessing the second half when the _PAGE_COMBO bit is set in the first half, which indicates that we are dealing with a "combo" page which represents 16x4k subpages. Anything else shouldn't have this bit set and thus not require loading from the second half. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/pte-hash64-64k.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index e05d26fa372fc..82b72207c51c9 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h @@ -47,7 +47,8 @@ * generic accessors and iterators here */ #define __real_pte(e,p) ((real_pte_t) { \ - (e), pte_val(*((p) + PTRS_PER_PTE)) }) + (e), ((e) & _PAGE_COMBO) ? \ + (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) #define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) #define __rpte_to_pte(r) ((r).pte) -- GitLab From 5ba762c9bb3ce2cc11e9e111cb3c476e84b91668 Mon Sep 17 00:00:00 2001 From: Adrian Reber <adrian@lisas.de> Date: Thu, 26 Mar 2009 02:05:42 +0000 Subject: [PATCH 0246/1002] powerpc/rtas: Fix watchdog driver temperature read functionality Using the RTAS watchdog driver to read out the temperature crashes on a PXCAB: Unable to handle kernel paging request for data at address 0xfe347b50 Faulting instruction address: 0xc00000000001af64 Oops: Kernel access of bad area, sig: 11 [#1] The wrong usage of "(void *)__pa(&temperature)" in rtas_call() is removed by using the function rtas_get_sensor() which does the right thing. Signed-off-by: Adrian Reber <adrian@lisas.de> Acked-by: Utz Bacher <utz.bacher@de.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- drivers/watchdog/wdrtas.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index a4fe7a38d9b03..3bde56bce63a3 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -218,16 +218,14 @@ static void wdrtas_timer_keepalive(void) */ static int wdrtas_get_temperature(void) { - long result; + int result; int temperature = 0; - result = rtas_call(wdrtas_token_get_sensor_state, 2, 2, - (void *)__pa(&temperature), - WDRTAS_THERMAL_SENSOR, 0); + result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature); if (result < 0) printk(KERN_WARNING "wdrtas: reading the thermal sensor " - "faild: %li\n", result); + "failed: %i\n", result); else temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ -- GitLab From 789547508f22e482825f52f813b59680408ec2c7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Tue, 23 Jun 2009 11:26:06 +0000 Subject: [PATCH 0247/1002] ide: fix ide_kill_rq() for special ide-{floppy,tape} driver requests Such requests should be failed with -EIO (like all other requests in this function) instead of being completed successfully. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 93b7886a2d6e3..95db5f03f6a28 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -152,7 +152,7 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) if ((media == ide_floppy || media == ide_tape) && drv_req) { rq->errors = 0; - ide_complete_rq(drive, 0, blk_rq_bytes(rq)); + ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); } else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; -- GitLab From 5e955245d6cf49c5ed26c7add7392ff5a6762bf4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Tue, 23 Jun 2009 11:27:27 +0000 Subject: [PATCH 0248/1002] ide: always kill the whole request on error * Use blk_rq_bytes() instead of obsolete ide_rq_bytes() in ide_kill_rq() and ide_floppy_do_request() for failed requests. [ bugfix part ] * Use blk_rq_bytes() instead of obsolete ide_rq_bytes() in ide_do_devset() and ide_complete_drive_reset(). Then remove ide_rq_bytes(). [ cleanup part ] Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-devsets.c | 2 +- drivers/ide/ide-eh.c | 2 +- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-io.c | 14 ++------------ include/linux/ide.h | 1 - 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c index 5bf958e5b1d5f..1099bf7cf968a 100644 --- a/drivers/ide/ide-devsets.c +++ b/drivers/ide/ide-devsets.c @@ -183,6 +183,6 @@ ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) err = setfunc(drive, *(int *)&rq->cmd[1]); if (err) rq->errors = err; - ide_complete_rq(drive, err, ide_rq_bytes(rq)); + ide_complete_rq(drive, err, blk_rq_bytes(rq)); return ide_stopped; } diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 2b91419796136..e9abf2c3c3354 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c @@ -149,7 +149,7 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { if (err <= 0 && rq->errors == 0) rq->errors = -EIO; - ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq)); + ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq)); } } diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 8b3f204f7d732..fefbdfc8db068 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -293,7 +293,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, drive->failed_pc = NULL; if (blk_fs_request(rq) == 0 && rq->errors == 0) rq->errors = -EIO; - ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); + ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); return ide_stopped; } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 95db5f03f6a28..d5f3c77beadd8 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -112,16 +112,6 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) } } -/* obsolete, blk_rq_bytes() should be used instead */ -unsigned int ide_rq_bytes(struct request *rq) -{ - if (blk_pc_request(rq)) - return blk_rq_bytes(rq); - else - return blk_rq_cur_sectors(rq) << 9; -} -EXPORT_SYMBOL_GPL(ide_rq_bytes); - int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) { ide_hwif_t *hwif = drive->hwif; @@ -152,14 +142,14 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) if ((media == ide_floppy || media == ide_tape) && drv_req) { rq->errors = 0; - ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); } else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; else if (blk_fs_request(rq) == 0 && rq->errors == 0) rq->errors = -EIO; - ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); } + + ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); } static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) diff --git a/include/linux/ide.h b/include/linux/ide.h index cf1f3888067ca..c6af7c44d46c8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1062,7 +1062,6 @@ int generic_ide_ioctl(ide_drive_t *, struct block_device *, unsigned, unsigned l extern int ide_vlb_clk; extern int ide_pci_clk; -unsigned int ide_rq_bytes(struct request *); int ide_end_rq(ide_drive_t *, struct request *, int, unsigned int); void ide_kill_rq(ide_drive_t *, struct request *); -- GitLab From a80cad950f2a562e60db1869dd29bc007c5a4b66 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <morimoto.kuninori@renesas.com> Date: Fri, 26 Jun 2009 07:05:39 +0000 Subject: [PATCH 0249/1002] sh: ms7724se: Add sh_eth support Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/boards/mach-se/7724/setup.c | 106 +++++++++++++++++++++++++- arch/sh/include/mach-se/mach/se7724.h | 5 ++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 9cd04bd558b88..21d18005fb4ad 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -23,6 +23,8 @@ #include <media/sh_mobile_ceu.h> #include <asm/io.h> #include <asm/heartbeat.h> +#include <asm/sh_eth.h> +#include <asm/clock.h> #include <asm/sh_keysc.h> #include <cpu/sh7724.h> #include <mach-se/mach/se7724.h> @@ -272,6 +274,34 @@ static struct platform_device keysc_device = { }, }; +/* SH Eth */ +static struct resource sh_eth_resources[] = { + [0] = { + .start = SH_ETH_ADDR, + .end = SH_ETH_ADDR + 0x1FC, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 91, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +struct sh_eth_plat_data sh_eth_plat = { + .phy = 0x1f, /* SMSC LAN8187 */ + .edmac_endian = EDMAC_LITTLE_ENDIAN, +}; + +static struct platform_device sh_eth_device = { + .name = "sh-eth", + .id = 0, + .dev = { + .platform_data = &sh_eth_plat, + }, + .num_resources = ARRAY_SIZE(sh_eth_resources), + .resource = sh_eth_resources, +}; + static struct platform_device *ms7724se_devices[] __initdata = { &heartbeat_device, &smc91x_eth_device, @@ -280,8 +310,57 @@ static struct platform_device *ms7724se_devices[] __initdata = { &ceu0_device, &ceu1_device, &keysc_device, + &sh_eth_device, }; +#define EEPROM_OP 0xBA206000 +#define EEPROM_ADR 0xBA206004 +#define EEPROM_DATA 0xBA20600C +#define EEPROM_STAT 0xBA206010 +#define EEPROM_STRT 0xBA206014 +static int __init sh_eth_is_eeprom_ready(void) +{ + int t = 10000; + + while (t--) { + if (!ctrl_inw(EEPROM_STAT)) + return 1; + cpu_relax(); + } + + printk(KERN_ERR "ms7724se can not access to eeprom\n"); + return 0; +} + +static void __init sh_eth_init(void) +{ + int i; + u16 mac[3]; + + /* check EEPROM status */ + if (!sh_eth_is_eeprom_ready()) + return; + + /* read MAC addr from EEPROM */ + for (i = 0 ; i < 3 ; i++) { + ctrl_outw(0x0, EEPROM_OP); /* read */ + ctrl_outw(i*2, EEPROM_ADR); + ctrl_outw(0x1, EEPROM_STRT); + if (!sh_eth_is_eeprom_ready()) + return; + + mac[i] = ctrl_inw(EEPROM_DATA); + mac[i] = ((mac[i] & 0xFF) << 8) | (mac[i] >> 8); /* swap */ + } + + /* reset sh-eth */ + ctrl_outl(0x1, SH_ETH_ADDR + 0x0); + + /* set MAC addr */ + ctrl_outl(((mac[0] << 16) | (mac[1])), SH_ETH_MAHR); + ctrl_outl((mac[2]), SH_ETH_MALR); +} + #define SW4140 0xBA201000 #define FPGA_OUT 0xBA200400 #define PORT_HIZA 0xA4050158 @@ -302,7 +381,8 @@ static int __init devices_setup(void) ctrl_outw(ctrl_inw(FPGA_OUT) & ~((1 << 1) | /* LAN */ (1 << 6) | /* VIDEO DAC */ - (1 << 12)), /* USB0 */ + (1 << 12) | /* USB0 */ + (1 << 14)), /* RMII */ FPGA_OUT); /* enable IRQ 0,1,2 */ @@ -404,6 +484,28 @@ static int __init devices_setup(void) gpio_request(GPIO_FN_KEYOUT1, NULL); gpio_request(GPIO_FN_KEYOUT0, NULL); + /* + * enable SH-Eth + * + * please remove J33 pin from your board !! + * + * ms7724 board should not use GPIO_FN_LNKSTA pin + * So, This time PTX5 is set to input pin + */ + gpio_request(GPIO_FN_RMII_RXD0, NULL); + gpio_request(GPIO_FN_RMII_RXD1, NULL); + gpio_request(GPIO_FN_RMII_TXD0, NULL); + gpio_request(GPIO_FN_RMII_TXD1, NULL); + gpio_request(GPIO_FN_RMII_REF_CLK, NULL); + gpio_request(GPIO_FN_RMII_TX_EN, NULL); + gpio_request(GPIO_FN_RMII_RX_ER, NULL); + gpio_request(GPIO_FN_RMII_CRS_DV, NULL); + gpio_request(GPIO_FN_MDIO, NULL); + gpio_request(GPIO_FN_MDC, NULL); + gpio_request(GPIO_PTX5, NULL); + gpio_direction_input(GPIO_PTX5); + sh_eth_init(); + if (sw & SW41_B) { /* SVGA */ lcdc_info.ch[0].lcd_cfg.xres = 800; @@ -437,7 +539,7 @@ static int __init devices_setup(void) } return platform_add_devices(ms7724se_devices, - ARRAY_SIZE(ms7724se_devices)); + ARRAY_SIZE(ms7724se_devices)); } device_initcall(devices_setup); diff --git a/arch/sh/include/mach-se/mach/se7724.h b/arch/sh/include/mach-se/mach/se7724.h index 74164b60d0dbb..29514a39d0f51 100644 --- a/arch/sh/include/mach-se/mach/se7724.h +++ b/arch/sh/include/mach-se/mach/se7724.h @@ -20,6 +20,11 @@ */ #include <asm/addrspace.h> +/* SH Eth */ +#define SH_ETH_ADDR (0xA4600000) +#define SH_ETH_MAHR (SH_ETH_ADDR + 0x1C0) +#define SH_ETH_MALR (SH_ETH_ADDR + 0x1C8) + #define PA_LED (0xba203000) /* 8bit LED */ #define IRQ_MODE (0xba200010) #define IRQ0_SR (0xba200014) -- GitLab From 0296e4254f3318e0dcad9706fa1daf8e5addc1e9 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Fri, 26 Jun 2009 11:15:37 +0800 Subject: [PATCH 0250/1002] ftrace: Fix the output of profile The first entry of the ftrace profile was always skipped when reading trace_stat/functionX. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A443D59.4080307@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/ftrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 71a52c172140f..f3716bf04df64 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -291,7 +291,9 @@ function_stat_next(void *v, int idx) pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); again: - rec++; + if (idx != 0) + rec++; + if ((void *)rec >= (void *)&pg->records[pg->index]) { pg = pg->next; if (!pg) -- GitLab From 7ed9f7e5db58c6e8c2b4b738a75d5dcd8e17aad5 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Date: Thu, 25 Jun 2009 12:31:37 -0700 Subject: [PATCH 0251/1002] fix RCU-callback-after-kmem_cache_destroy problem in sl[aou]b Jesper noted that kmem_cache_destroy() invokes synchronize_rcu() rather than rcu_barrier() in the SLAB_DESTROY_BY_RCU case, which could result in RCU callbacks accessing a kmem_cache after it had been destroyed. Cc: <stable@kernel.org> Acked-by: Matt Mackall <mpm@selenic.com> Reported-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> --- mm/slab.c | 2 +- mm/slob.c | 2 ++ mm/slub.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mm/slab.c b/mm/slab.c index e74a16e4ced60..5241b6598ba38 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2547,7 +2547,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep) } if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) - synchronize_rcu(); + rcu_barrier(); __kmem_cache_destroy(cachep); mutex_unlock(&cache_chain_mutex); diff --git a/mm/slob.c b/mm/slob.c index c78742defdc64..9641da3d5e58d 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -595,6 +595,8 @@ EXPORT_SYMBOL(kmem_cache_create); void kmem_cache_destroy(struct kmem_cache *c) { kmemleak_free(c); + if (c->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); slob_free(c, sizeof(struct kmem_cache)); } EXPORT_SYMBOL(kmem_cache_destroy); diff --git a/mm/slub.c b/mm/slub.c index 819f056b39c6f..a9201d83178b8 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2595,6 +2595,8 @@ static inline int kmem_cache_close(struct kmem_cache *s) */ void kmem_cache_destroy(struct kmem_cache *s) { + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); down_write(&slub_lock); s->refcount--; if (!s->refcount) { -- GitLab From 7e25a2422987a37729706b18583d177966919d2a Mon Sep 17 00:00:00 2001 From: Chris Wright <chrisw@redhat.com> Date: Thu, 25 Jun 2009 18:52:05 -0700 Subject: [PATCH 0252/1002] intel-iommu: fix Identity Mapping to be arch independent Drop the e820 scanning and use existing function for finding valid RAM regions to add to 1:1 mapping. Signed-off-by: Chris Wright <chrisw@redhat.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index e53eacd75c8da..420afa8872837 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -39,7 +39,6 @@ #include <linux/sysdev.h> #include <asm/cacheflush.h> #include <asm/iommu.h> -#include <asm/e820.h> #include "pci.h" #define ROOT_SIZE VTD_PAGE_SIZE @@ -1908,7 +1907,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, rmrr->end_address + 1); } -#ifdef CONFIG_DMAR_GFX_WA struct iommu_prepare_data { struct pci_dev *pdev; int ret; @@ -1943,6 +1941,7 @@ static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) return data.ret; } +#ifdef CONFIG_DMAR_GFX_WA static void __init iommu_prepare_gfx_mapping(void) { struct pci_dev *pdev = NULL; @@ -2081,7 +2080,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, static int iommu_prepare_static_identity_mapping(void) { - int i; struct pci_dev *pdev = NULL; int ret; @@ -2091,17 +2089,10 @@ static int iommu_prepare_static_identity_mapping(void) printk(KERN_INFO "IOMMU: Setting identity map:\n"); for_each_pci_dev(pdev) { - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - - if (ei->type == E820_RAM) { - ret = iommu_prepare_identity_map(pdev, - ei->addr, ei->addr + ei->size); - if (ret) { - printk(KERN_INFO "1:1 mapping to one domain failed.\n"); - return -EFAULT; - } - } + ret = iommu_prepare_with_active_regions(pdev); + if (ret) { + printk(KERN_INFO "1:1 mapping to one domain failed.\n"); + return -EFAULT; } ret = domain_add_dev_info(si_domain, pdev); if (ret) -- GitLab From 584fcff428bde3b9985ba21498764e9dba2fd3ce Mon Sep 17 00:00:00 2001 From: Borislav Petkov <borislav.petkov@amd.com> Date: Wed, 10 Jun 2009 18:29:54 +0200 Subject: [PATCH 0253/1002] amd64_edac: check only ECC bit in amd64_determine_edac_cap Checking whether the machine is using ECC enabled DRAM is done through testing the DimmEccEn bit in the DRAM Cfg Low register (F2x[1,0]90). Do that instead of testing all bits from the DimmEccEn upwards. Also, remove mci->edac_cap assignment and use value returned from amd64_determine_edac_cap(). Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> --- drivers/edac/amd64_edac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c36bf40568cf8..3b76605330e97 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -754,13 +754,13 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt) static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) { int bit; - enum dev_type edac_cap = EDAC_NONE; + enum dev_type edac_cap = EDAC_FLAG_NONE; bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) ? 19 : 17; - if (pvt->dclr0 >> BIT(bit)) + if (pvt->dclr0 & BIT(bit)) edac_cap = EDAC_FLAG_SECDED; return edac_cap; @@ -3006,7 +3006,6 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE; - mci->edac_cap = EDAC_FLAG_NONE; if (pvt->nbcap & K8_NBCAP_SECDED) mci->edac_ctl_cap |= EDAC_FLAG_SECDED; -- GitLab From 30c875cbc1836a03a1acc6c998fa8a04f29f8f73 Mon Sep 17 00:00:00 2001 From: Borislav Petkov <borislav.petkov@amd.com> Date: Mon, 22 Jun 2009 19:42:24 +0200 Subject: [PATCH 0254/1002] amd64_edac: fix ecc_enable_override handling amd64_check_ecc_enabled() returns non-zero status when ECC checking/correcting is disabled and this fails further loading of the driver even when 'ecc_enable_override' boot param is used. Fix that by clearing return status in that case. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> --- drivers/edac/amd64_edac.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 3b76605330e97..8497963a61f65 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2966,7 +2966,12 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) " Use of the override can cause " "unknown side effects.\n"); ret = -ENODEV; - } + } else + /* + * enable further driver loading if ECC enable is + * overridden. + */ + ret = 0; } else { amd64_printk(KERN_INFO, "ECC is enabled by BIOS, Proceeding " -- GitLab From 37da045067b4e923190662e21029005ea53bfaa1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov <borislav.petkov@amd.com> Date: Wed, 10 Jun 2009 17:36:57 +0200 Subject: [PATCH 0255/1002] amd64_edac: misc small cleanups - cleanup debug calls - shorten function names - cleanup error exit paths Signed-off-by: Borislav Petkov <borislav.petkov@amd.com> --- drivers/edac/amd64_edac.c | 13 +++++++------ drivers/edac/amd64_edac.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8497963a61f65..858fe60372236 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1269,7 +1269,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) if (channels == 0) channels = 1; - debugf0("DIMM count= %d\n", channels); + debugf0("MCT channel count: %d\n", channels); return channels; @@ -3056,7 +3056,7 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, if (!pvt) goto err_exit; - pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl); + pvt->mc_node_id = get_node_id(dram_f2_ctl); pvt->dram_f2_ctl = dram_f2_ctl; pvt->ext_model = boot_cpu_data.x86_model >> 4; @@ -3183,8 +3183,7 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev, { int ret = 0; - debugf0("(MC node=%d,mc_type='%s')\n", - get_mc_node_id_from_pdev(pdev), + debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), get_amd_family_name(mc_type->driver_data)); ret = pci_enable_device(pdev); @@ -3323,15 +3322,17 @@ static int __init amd64_edac_init(void) err = amd64_init_2nd_stage(pvt_lookup[nb]); if (err) - goto err_exit; + goto err_2nd_stage; } amd64_setup_pci_device(); return 0; +err_2nd_stage: + debugf0("2nd stage failed\n"); + err_exit: - debugf0("'finish_setup' stage failed\n"); pci_unregister_driver(&amd64_pci_driver); return err; diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index a159957e167b1..ba73015af8e48 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -444,7 +444,7 @@ enum { #define K8_MSR_MC4ADDR 0x0412 /* AMD sets the first MC device at device ID 0x18. */ -static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev) +static inline int get_node_id(struct pci_dev *pdev) { return PCI_SLOT(pdev->devfn) - 0x18; } -- GitLab From 8cb76d99d715741637b6d0884f389e17e9cb05d2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Fri, 26 Jun 2009 16:28:00 +0200 Subject: [PATCH 0256/1002] perf_counter tools: Prepare a small callchain framework We plan to display the callchains depending on some user-configurable parameters. To gather the callchains stats from the recorded stream in a fast way, this patch introduces an ad hoc radix tree adapted for callchains and also a rbtree to sort these callchains once we have gathered every events from the stream. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246026481-8314-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 1 + tools/perf/builtin-report.c | 5 -- tools/perf/perf.h | 5 ++ tools/perf/util/callchain.c | 174 ++++++++++++++++++++++++++++++++++++ tools/perf/util/callchain.h | 33 +++++++ 5 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 tools/perf/util/callchain.c create mode 100644 tools/perf/util/callchain.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d3887ed51a640..1c1296d8a64bd 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -329,6 +329,7 @@ LIB_OBJS += util/symbol.o LIB_OBJS += util/color.o LIB_OBJS += util/pager.o LIB_OBJS += util/header.o +LIB_OBJS += util/callchain.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 681c2233f8827..28d1cb2127e9e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -62,11 +62,6 @@ struct ip_event { unsigned char __more_data[]; }; -struct ip_callchain { - u64 nr; - u64 ips[0]; -}; - struct mmap_event { struct perf_event_header header; u32 pid, tid; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 16c84fd73c86b..a49842b69a59c 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -66,4 +66,9 @@ sys_perf_counter_open(struct perf_counter_attr *attr, #define MAX_COUNTERS 256 #define MAX_NR_CPUS 256 +struct ip_callchain { + u64 nr; + u64 ips[0]; +}; + #endif diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c new file mode 100644 index 0000000000000..ad3c285789611 --- /dev/null +++ b/tools/perf/util/callchain.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com> + * + * Handle the callchains from the stream in an ad-hoc radix tree and then + * sort them in an rbtree. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <errno.h> + +#include "callchain.h" + + +static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) +{ + struct rb_node **p = &root->rb_node; + struct rb_node *parent = NULL; + struct callchain_node *rnode; + + while (*p) { + parent = *p; + rnode = rb_entry(parent, struct callchain_node, rb_node); + + if (rnode->hit < chain->hit) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&chain->rb_node, parent, p); + rb_insert_color(&chain->rb_node, root); +} + +/* + * Once we get every callchains from the stream, we can now + * sort them by hit + */ +void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) +{ + struct callchain_node *child; + + list_for_each_entry(child, &node->children, brothers) + sort_chain_to_rbtree(rb_root, child); + + if (node->hit) + rb_insert_callchain(rb_root, node); +} + +static struct callchain_node *create_child(struct callchain_node *parent) +{ + struct callchain_node *new; + + new = malloc(sizeof(*new)); + if (!new) { + perror("not enough memory to create child for code path tree"); + return NULL; + } + new->parent = parent; + INIT_LIST_HEAD(&new->children); + INIT_LIST_HEAD(&new->val); + list_add_tail(&new->brothers, &parent->children); + + return new; +} + +static void +fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) +{ + int i; + + for (i = start; i < chain->nr; i++) { + struct callchain_list *call; + + call = malloc(sizeof(*chain)); + if (!call) { + perror("not enough memory for the code path tree"); + return; + } + call->ip = chain->ips[i]; + list_add_tail(&call->list, &node->val); + } + node->val_nr = i - start; +} + +static void add_child(struct callchain_node *parent, struct ip_callchain *chain) +{ + struct callchain_node *new; + + new = create_child(parent); + fill_node(new, chain, parent->val_nr); + + new->hit = 1; +} + +static void +split_add_child(struct callchain_node *parent, struct ip_callchain *chain, + struct callchain_list *to_split, int idx) +{ + struct callchain_node *new; + + /* split */ + new = create_child(parent); + list_move_tail(&to_split->list, &new->val); + new->hit = parent->hit; + parent->hit = 0; + parent->val_nr = idx; + + /* create the new one */ + add_child(parent, chain); +} + +static int +__append_chain(struct callchain_node *root, struct ip_callchain *chain, + int start); + +static int +__append_chain_children(struct callchain_node *root, struct ip_callchain *chain) +{ + struct callchain_node *rnode; + + /* lookup in childrens */ + list_for_each_entry(rnode, &root->children, brothers) { + int ret = __append_chain(rnode, chain, root->val_nr); + if (!ret) + return 0; + } + return -1; +} + +static int +__append_chain(struct callchain_node *root, struct ip_callchain *chain, + int start) +{ + struct callchain_list *cnode; + int i = start; + bool found = false; + + /* lookup in the current node */ + list_for_each_entry(cnode, &root->val, list) { + if (cnode->ip != chain->ips[i++]) + break; + if (!found) + found = true; + if (i == chain->nr) + break; + } + + /* matches not, relay on the parent */ + if (!found) + return -1; + + /* we match only a part of the node. Split it and add the new chain */ + if (i < root->val_nr) { + split_add_child(root, chain, cnode, i); + return 0; + } + + /* we match 100% of the path, increment the hit */ + if (i == root->val_nr) { + root->hit++; + return 0; + } + + return __append_chain_children(root, chain); +} + +void append_chain(struct callchain_node *root, struct ip_callchain *chain) +{ + if (__append_chain_children(root, chain) == -1) + add_child(root, chain); +} diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h new file mode 100644 index 0000000000000..fa1cd2f71fd3b --- /dev/null +++ b/tools/perf/util/callchain.h @@ -0,0 +1,33 @@ +#ifndef __PERF_CALLCHAIN_H +#define __PERF_CALLCHAIN_H + +#include "../perf.h" +#include "list.h" +#include "rbtree.h" + + +struct callchain_node { + struct callchain_node *parent; + struct list_head brothers; + struct list_head children; + struct list_head val; + struct rb_node rb_node; + int val_nr; + int hit; +}; + +struct callchain_list { + unsigned long ip; + struct list_head list; +}; + +static inline void callchain_init(struct callchain_node *node) +{ + INIT_LIST_HEAD(&node->brothers); + INIT_LIST_HEAD(&node->children); + INIT_LIST_HEAD(&node->val); +} + +void append_chain(struct callchain_node *root, struct ip_callchain *chain); +void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); +#endif -- GitLab From f55c555226b1010b249730ec6b232e5470286950 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Fri, 26 Jun 2009 16:28:01 +0200 Subject: [PATCH 0257/1002] perf report: Print sorted callchains per histogram entries Use the newly created callchains radix tree to gather the chains stats from the recorded events and then print the callchains for all of them, sorted by hits, using the "-c" parameter with perf report. Example: 66.15% [k] atm_clip_exit 63.08% 0xffffffffffffff80 0xffffffff810196a8 0xffffffff810c14c8 0xffffffff8101a79c 0xffffffff810194f3 0xffffffff8106ab7f 0xffffffff8106abe5 0xffffffff8106acde 0xffffffff8100d94b 0xffffffff8153e7ea [...] 1.54% 0xffffffffffffff80 0xffffffff810196a8 0xffffffff810c14c8 0xffffffff8101a79c [...] Symbols are not yet resolved. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246026481-8314-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 82 ++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 28d1cb2127e9e..ed391db9e0f8d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -15,6 +15,7 @@ #include "util/rbtree.h" #include "util/symbol.h" #include "util/string.h" +#include "util/callchain.h" #include "perf.h" #include "util/header.h" @@ -52,6 +53,7 @@ static char *parent_pattern = default_parent_pattern; static regex_t parent_regex; static int exclude_other = 1; +static int callchain; static u64 sample_type; @@ -488,17 +490,19 @@ static size_t threads__fprintf(FILE *fp) static struct rb_root hist; struct hist_entry { - struct rb_node rb_node; - - struct thread *thread; - struct map *map; - struct dso *dso; - struct symbol *sym; - struct symbol *parent; - u64 ip; - char level; - - u64 count; + struct rb_node rb_node; + + struct thread *thread; + struct map *map; + struct dso *dso; + struct symbol *sym; + struct symbol *parent; + u64 ip; + char level; + struct callchain_node callchain; + struct rb_root sorted_chain; + + u64 count; }; /* @@ -768,6 +772,48 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) return cmp; } +static size_t +callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) +{ + struct callchain_list *chain; + size_t ret = 0; + + if (!self) + return 0; + + ret += callchain__fprintf(fp, self->parent, total_samples); + + + list_for_each_entry(chain, &self->val, list) + ret += fprintf(fp, " %p\n", (void *)chain->ip); + + return ret; +} + +static size_t +hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, + u64 total_samples) +{ + struct rb_node *rb_node; + struct callchain_node *chain; + size_t ret = 0; + + rb_node = rb_first(&self->sorted_chain); + while (rb_node) { + double percent; + + chain = rb_entry(rb_node, struct callchain_node, rb_node); + percent = chain->hit * 100.0 / total_samples; + ret += fprintf(fp, " %6.2f%%\n", percent); + ret += callchain__fprintf(fp, chain, total_samples); + ret += fprintf(fp, "\n"); + rb_node = rb_next(rb_node); + } + + return ret; +} + + static size_t hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) { @@ -808,6 +854,9 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) ret += fprintf(fp, "\n"); + if (callchain) + hist_entry_callchain__fprintf(fp, self, total_samples); + return ret; } @@ -892,6 +941,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, .level = level, .count = count, .parent = NULL, + .sorted_chain = RB_ROOT }; int cmp; @@ -934,6 +984,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, if (!cmp) { he->count += count; + if (callchain) + append_chain(&he->callchain, chain); return 0; } @@ -947,6 +999,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, if (!he) return -ENOMEM; *he = entry; + if (callchain) { + callchain_init(&he->callchain); + append_chain(&he->callchain, chain); + } rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, &hist); @@ -1023,6 +1079,9 @@ static void output__insert_entry(struct hist_entry *he) struct rb_node *parent = NULL; struct hist_entry *iter; + if (callchain) + sort_chain_to_rbtree(&he->sorted_chain, &he->callchain); + while (*p != NULL) { parent = *p; iter = rb_entry(parent, struct hist_entry, rb_node); @@ -1599,6 +1658,7 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &exclude_other, "Only display entries with parent-match"), + OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), OPT_END() }; -- GitLab From 39562e783928e3ea9ee2cbce99a756ab48d3c06a Mon Sep 17 00:00:00 2001 From: Christof Schmitt <christof.schmitt@de.ibm.com> Date: Fri, 26 Jun 2009 16:30:43 +0200 Subject: [PATCH 0258/1002] [SCSI] FC transport: Locking fix for common-code FC pass-through patch Fix this: ------------[ cut here ]------------ Badness at block/blk-core.c:244 CPU: 0 Tainted: G W 2.6.31-rc1-00004-gd3a263a #3 Process zfcp_wq (pid: 901, task: 000000002fb7a038, ksp: 000000002f02bc78) Krnl PSW : 0704300180000000 00000000002141ba (blk_remove_plug+0xb2/0xb8) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:3 PM:0 EA:3 Krnl GPRS: 0000000000000001 0000000000000001 0000000022811440 0000000022811798 000000000027ff4e 0000000000000000 0000000000000000 000000002f00f000 070000000006a0f4 000000002af70000 000000002af2a800 00000000228d1c00 0000000022811440 000000000050c708 000000002f02bca8 000000002f02bc80 Krnl Code: 00000000002141b0: b9140022 lgfr %r2,%r2 00000000002141b4: 07fe bcr 15,%r14 00000000002141b6: a7f40001 brc 15,2141b8 >00000000002141ba: a7f4ffbe brc 15,214136 00000000002141be: 0707 bcr 0,%r7 00000000002141c0: ebaff0680024 stmg %r10,%r15,104(%r15) 00000000002141c6: c0d00017c2a9 larl %r13,50c718 00000000002141cc: a7f13fc0 tmll %r15,16320 Call Trace: ([<000000000050e7d8>] C.272.16122+0x88/0x110) [<00000000002141ec>] __blk_run_queue+0x2c/0x154 [<000000000028013a>] fc_remote_port_add+0x85e/0x95c [<000000000037596e>] zfcp_scsi_rport_work+0xe6/0x148 [<000000000006908c>] worker_thread+0x25c/0x318 [<000000000006f10c>] kthread+0x94/0x9c [<000000000001c2b2>] kernel_thread_starter+0x6/0xc [<000000000001c2ac>] kernel_thread_starter+0x0/0xc INFO: lockdep is turned off. Last Breaking-Event-Address: [<00000000002141b6>] blk_remove_plug+0xae/0xb8 The FC pass-through support triggers the WARN_ON(!irqs_disabled()) in blk_plug_device. Since blk_plug_device requires being called with disabled interrupts, use spin_lock_irqsave in fc_bsg_goose_queue to disable the interrupts before calling into the block layer. Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Acked-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/scsi_transport_fc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2eee9e6e4fe8f..292c02f810d04 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3670,13 +3670,14 @@ static void fc_bsg_goose_queue(struct fc_rport *rport) { int flagset; + unsigned long flags; if (!rport->rqst_q) return; get_device(&rport->dev); - spin_lock(rport->rqst_q->queue_lock); + spin_lock_irqsave(rport->rqst_q->queue_lock, flags); flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) && !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags); if (flagset) @@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) __blk_run_queue(rport->rqst_q); if (flagset) queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q); - spin_unlock(rport->rqst_q->queue_lock); + spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags); put_device(&rport->dev); } -- GitLab From 19d2e755436054dfc2be640bffc32e427c37ac3d Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Fri, 26 Jun 2009 13:10:23 +0200 Subject: [PATCH 0259/1002] perf_counter: Complete counter swap Complete the counter swap by indeed switching the times too and updating the userpage after modifying the counter values. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246014623.31755.195.camel@twins> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/perf_counter.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index f2f2326965870..66ab1e9d12946 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1048,9 +1048,14 @@ static void __perf_counter_sync_stat(struct perf_counter *counter, value = atomic64_xchg(&counter->count, value); atomic64_set(&next_counter->count, value); + swap(counter->total_time_enabled, next_counter->total_time_enabled); + swap(counter->total_time_running, next_counter->total_time_running); + /* - * XXX also sync time_enabled and time_running ? + * Since we swizzled the values, update the user visible data too. */ + perf_counter_update_userpage(counter); + perf_counter_update_userpage(next_counter); } #define list_next_entry(pos, member) \ -- GitLab From b9389796fa4c87fbdff33816e317cdae5f36dd0b Mon Sep 17 00:00:00 2001 From: Anton Vorontsov <avorontsov@ru.mvista.com> Date: Fri, 26 Jun 2009 09:28:42 -0700 Subject: [PATCH 0260/1002] sky2: Fix checksum endianness sky2 driver on PowerPC targets floods kernel log with following errors: eth1: hw csum failure. Call Trace: [ef84b8a0] [c00075e4] show_stack+0x50/0x160 (unreliable) [ef84b8d0] [c02fa178] netdev_rx_csum_fault+0x3c/0x5c [ef84b8f0] [c02f6920] __skb_checksum_complete_head+0x7c/0x84 [ef84b900] [c02f693c] __skb_checksum_complete+0x14/0x24 [ef84b910] [c0337e08] tcp_v4_rcv+0x4c8/0x6f8 [ef84b940] [c031a9c8] ip_local_deliver+0x98/0x210 [ef84b960] [c031a788] ip_rcv+0x38c/0x534 [ef84b990] [c0300338] netif_receive_skb+0x260/0x36c [ef84b9c0] [c025de00] sky2_poll+0x5dc/0xcf8 [ef84ba20] [c02fb7fc] net_rx_action+0xc0/0x144 The NIC is Yukon-2 EC chip revision 1. Converting checksum field from le16 to CPU byte order fixes the issue. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7681d28c53d77..daf961ab68bc2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2495,7 +2495,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) if (likely(status >> 16 == (status & 0xffff))) { skb = sky2->rx_ring[sky2->rx_next].skb; skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = status & 0xffff; + skb->csum = le16_to_cpu(status); } else { printk(KERN_NOTICE PFX "%s: hardware receive " "checksum problem (status = %#x)\n", -- GitLab From e0a2a1601bec01243bcad44414d06f59dae2eedb Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Fri, 26 Jun 2009 17:38:25 +0100 Subject: [PATCH 0261/1002] kmemleak: Enable task stacks scanning by default This is to reduce the number of false positives reported. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- Documentation/kmemleak.txt | 8 ++++---- mm/kmemleak.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index f655308064d76..9426e94f291ac 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -31,12 +31,12 @@ Memory scanning parameters can be modified at run-time by writing to the /sys/kernel/debug/kmemleak file. The following parameters are supported: off - disable kmemleak (irreversible) - stack=on - enable the task stacks scanning + stack=on - enable the task stacks scanning (default) stack=off - disable the tasks stacks scanning - scan=on - start the automatic memory scanning thread + scan=on - start the automatic memory scanning thread (default) scan=off - stop the automatic memory scanning thread - scan=<secs> - set the automatic memory scanning period in seconds (0 - to disable it) + scan=<secs> - set the automatic memory scanning period in seconds + (default 600, 0 to stop the automatic scanning) Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on the kernel command line. diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 17096d1b59b27..a38418a95d33f 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -194,7 +194,7 @@ static unsigned long jiffies_min_age; /* delay between automatic memory scannings */ static signed long jiffies_scan_wait; /* enables or disables the task stacks scanning */ -static int kmemleak_stack_scan; +static int kmemleak_stack_scan = 1; /* mutex protecting the memory scanning */ static DEFINE_MUTEX(scan_mutex); /* mutex protecting the access to the /sys/kernel/debug/kmemleak file */ -- GitLab From bab4a34afc301fdb81b6ea0e3098d96fc356e03a Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Fri, 26 Jun 2009 17:38:26 +0100 Subject: [PATCH 0262/1002] kmemleak: Simplify the reports logged by the scanning thread Because of false positives, the memory scanning thread may print too much information. This patch changes the scanning thread to only print the number of newly suspected leaks. Further information can be read from the /sys/kernel/debug/kmemleak file. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- Documentation/kmemleak.txt | 6 ++-- mm/kmemleak.c | 61 ++++++++++---------------------------- 2 files changed, 19 insertions(+), 48 deletions(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index 9426e94f291ac..c06f7ba649935 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -16,9 +16,9 @@ Usage ----- CONFIG_DEBUG_KMEMLEAK in "Kernel hacking" has to be enabled. A kernel -thread scans the memory every 10 minutes (by default) and prints any new -unreferenced objects found. To trigger an intermediate scan and display -all the possible memory leaks: +thread scans the memory every 10 minutes (by default) and prints the +number of new unreferenced objects found. To trigger an intermediate +scan and display the details of all the possible memory leaks: # mount -t debugfs nodev /sys/kernel/debug/ # cat /sys/kernel/debug/kmemleak diff --git a/mm/kmemleak.c b/mm/kmemleak.c index a38418a95d33f..4130a4889fa9a 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -278,15 +278,6 @@ static int color_gray(const struct kmemleak_object *object) return object->min_count != -1 && object->count >= object->min_count; } -/* - * Objects are considered referenced if their color is gray and they have not - * been deleted. - */ -static int referenced_object(struct kmemleak_object *object) -{ - return (object->flags & OBJECT_ALLOCATED) && color_gray(object); -} - /* * Objects are considered unreferenced only if their color is white, they have * not be deleted and have a minimum age to avoid false positives caused by @@ -299,38 +290,23 @@ static int unreferenced_object(struct kmemleak_object *object) } /* - * Printing of the (un)referenced objects information, either to the seq file - * or to the kernel log. The print_referenced/print_unreferenced functions - * must be called with the object->lock held. + * Printing of the unreferenced objects information to the seq file. The + * print_unreferenced function must be called with the object->lock held. */ -#define print_helper(seq, x...) do { \ - struct seq_file *s = (seq); \ - if (s) \ - seq_printf(s, x); \ - else \ - pr_info(x); \ -} while (0) - -static void print_referenced(struct kmemleak_object *object) -{ - pr_info("referenced object 0x%08lx (size %zu)\n", - object->pointer, object->size); -} - static void print_unreferenced(struct seq_file *seq, struct kmemleak_object *object) { int i; - print_helper(seq, "unreferenced object 0x%08lx (size %zu):\n", - object->pointer, object->size); - print_helper(seq, " comm \"%s\", pid %d, jiffies %lu\n", - object->comm, object->pid, object->jiffies); - print_helper(seq, " backtrace:\n"); + seq_printf(seq, "unreferenced object 0x%08lx (size %zu):\n", + object->pointer, object->size); + seq_printf(seq, " comm \"%s\", pid %d, jiffies %lu\n", + object->comm, object->pid, object->jiffies); + seq_printf(seq, " backtrace:\n"); for (i = 0; i < object->trace_len; i++) { void *ptr = (void *)object->trace[i]; - print_helper(seq, " [<%p>] %pS\n", ptr, ptr); + seq_printf(seq, " [<%p>] %pS\n", ptr, ptr); } } @@ -571,8 +547,6 @@ static void delete_object(unsigned long ptr) * cannot be freed when it is being scanned. */ spin_lock_irqsave(&object->lock, flags); - if (object->flags & OBJECT_REPORTED) - print_referenced(object); object->flags &= ~OBJECT_ALLOCATED; spin_unlock_irqrestore(&object->lock, flags); put_object(object); @@ -1073,33 +1047,30 @@ static int kmemleak_scan_thread(void *arg) while (!kthread_should_stop()) { struct kmemleak_object *object; signed long timeout = jiffies_scan_wait; + int new_leaks = 0; mutex_lock(&scan_mutex); kmemleak_scan(); - reported_leaks = 0; rcu_read_lock(); list_for_each_entry_rcu(object, &object_list, object_list) { unsigned long flags; - if (reported_leaks >= REPORTS_NR) - break; spin_lock_irqsave(&object->lock, flags); - if (!(object->flags & OBJECT_REPORTED) && - unreferenced_object(object)) { - print_unreferenced(NULL, object); + if (unreferenced_object(object) && + !(object->flags & OBJECT_REPORTED)) { object->flags |= OBJECT_REPORTED; - reported_leaks++; - } else if ((object->flags & OBJECT_REPORTED) && - referenced_object(object)) { - print_referenced(object); - object->flags &= ~OBJECT_REPORTED; + new_leaks++; } spin_unlock_irqrestore(&object->lock, flags); } rcu_read_unlock(); + if (new_leaks) + pr_info("%d new suspected memory leaks (see " + "/sys/kernel/debug/kmemleak)\n", new_leaks); + mutex_unlock(&scan_mutex); /* wait before the next scan */ while (timeout && !kthread_should_stop()) -- GitLab From 4698c1f2bbe44ce852ef1a6716973c1f5401a4c4 Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Fri, 26 Jun 2009 17:38:27 +0100 Subject: [PATCH 0263/1002] kmemleak: Do not trigger a scan when reading the debug/kmemleak file Since there is a kernel thread for automatically scanning the memory, it makes sense for the debug/kmemleak file to only show its findings. This patch also adds support for "echo scan > debug/kmemleak" to trigger an intermediate memory scan and eliminates the kmemleak_mutex (scan_mutex covers all the cases now). Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- Documentation/kmemleak.txt | 9 +++- mm/kmemleak.c | 90 +++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/Documentation/kmemleak.txt b/Documentation/kmemleak.txt index c06f7ba649935..89068030b01bb 100644 --- a/Documentation/kmemleak.txt +++ b/Documentation/kmemleak.txt @@ -17,12 +17,16 @@ Usage CONFIG_DEBUG_KMEMLEAK in "Kernel hacking" has to be enabled. A kernel thread scans the memory every 10 minutes (by default) and prints the -number of new unreferenced objects found. To trigger an intermediate -scan and display the details of all the possible memory leaks: +number of new unreferenced objects found. To display the details of all +the possible memory leaks: # mount -t debugfs nodev /sys/kernel/debug/ # cat /sys/kernel/debug/kmemleak +To trigger an intermediate memory scan: + + # echo scan > /sys/kernel/debug/kmemleak + Note that the orphan objects are listed in the order they were allocated and one object at the beginning of the list may cause other subsequent objects to be reported as orphan. @@ -37,6 +41,7 @@ Memory scanning parameters can be modified at run-time by writing to the scan=off - stop the automatic memory scanning thread scan=<secs> - set the automatic memory scanning period in seconds (default 600, 0 to stop the automatic scanning) + scan - trigger a memory scan Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on the kernel command line. diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 4130a4889fa9a..e96e0ec6a56eb 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -48,10 +48,10 @@ * scanned. This list is only modified during a scanning episode when the * scan_mutex is held. At the end of a scan, the gray_list is always empty. * Note that the kmemleak_object.use_count is incremented when an object is - * added to the gray_list and therefore cannot be freed - * - kmemleak_mutex (mutex): prevents multiple users of the "kmemleak" debugfs - * file together with modifications to the memory scanning parameters - * including the scan_thread pointer + * added to the gray_list and therefore cannot be freed. This mutex also + * prevents multiple users of the "kmemleak" debugfs file together with + * modifications to the memory scanning parameters including the scan_thread + * pointer * * The kmemleak_object structures have a use_count incremented or decremented * using the get_object()/put_object() functions. When the use_count becomes @@ -195,10 +195,8 @@ static unsigned long jiffies_min_age; static signed long jiffies_scan_wait; /* enables or disables the task stacks scanning */ static int kmemleak_stack_scan = 1; -/* mutex protecting the memory scanning */ +/* protects the memory scanning, parameters and debug/kmemleak file access */ static DEFINE_MUTEX(scan_mutex); -/* mutex protecting the access to the /sys/kernel/debug/kmemleak file */ -static DEFINE_MUTEX(kmemleak_mutex); /* number of leaks reported (for limitation purposes) */ static int reported_leaks; @@ -927,6 +925,7 @@ static void kmemleak_scan(void) struct kmemleak_object *object, *tmp; struct task_struct *task; int i; + int new_leaks = 0; /* prepare the kmemleak_object's */ rcu_read_lock(); @@ -1024,6 +1023,26 @@ static void kmemleak_scan(void) object = tmp; } WARN_ON(!list_empty(&gray_list)); + + /* + * Scanning result reporting. + */ + rcu_read_lock(); + list_for_each_entry_rcu(object, &object_list, object_list) { + spin_lock_irqsave(&object->lock, flags); + if (unreferenced_object(object) && + !(object->flags & OBJECT_REPORTED)) { + object->flags |= OBJECT_REPORTED; + new_leaks++; + } + spin_unlock_irqrestore(&object->lock, flags); + } + rcu_read_unlock(); + + if (new_leaks) + pr_info("%d new suspected memory leaks (see " + "/sys/kernel/debug/kmemleak)\n", new_leaks); + } /* @@ -1045,33 +1064,12 @@ static int kmemleak_scan_thread(void *arg) } while (!kthread_should_stop()) { - struct kmemleak_object *object; signed long timeout = jiffies_scan_wait; - int new_leaks = 0; mutex_lock(&scan_mutex); - kmemleak_scan(); - - rcu_read_lock(); - list_for_each_entry_rcu(object, &object_list, object_list) { - unsigned long flags; - - spin_lock_irqsave(&object->lock, flags); - if (unreferenced_object(object) && - !(object->flags & OBJECT_REPORTED)) { - object->flags |= OBJECT_REPORTED; - new_leaks++; - } - spin_unlock_irqrestore(&object->lock, flags); - } - rcu_read_unlock(); - - if (new_leaks) - pr_info("%d new suspected memory leaks (see " - "/sys/kernel/debug/kmemleak)\n", new_leaks); - mutex_unlock(&scan_mutex); + /* wait before the next scan */ while (timeout && !kthread_should_stop()) timeout = schedule_timeout_interruptible(timeout); @@ -1084,7 +1082,7 @@ static int kmemleak_scan_thread(void *arg) /* * Start the automatic memory scanning thread. This function must be called - * with the kmemleak_mutex held. + * with the scan_mutex held. */ void start_scan_thread(void) { @@ -1099,7 +1097,7 @@ void start_scan_thread(void) /* * Stop the automatic memory scanning thread. This function must be called - * with the kmemleak_mutex held. + * with the scan_mutex held. */ void stop_scan_thread(void) { @@ -1119,10 +1117,8 @@ static void *kmemleak_seq_start(struct seq_file *seq, loff_t *pos) struct kmemleak_object *object; loff_t n = *pos; - if (!n) { - kmemleak_scan(); + if (!n) reported_leaks = 0; - } if (reported_leaks >= REPORTS_NR) return NULL; @@ -1206,13 +1202,10 @@ static int kmemleak_open(struct inode *inode, struct file *file) if (!atomic_read(&kmemleak_enabled)) return -EBUSY; - ret = mutex_lock_interruptible(&kmemleak_mutex); + ret = mutex_lock_interruptible(&scan_mutex); if (ret < 0) goto out; if (file->f_mode & FMODE_READ) { - ret = mutex_lock_interruptible(&scan_mutex); - if (ret < 0) - goto kmemleak_unlock; ret = seq_open(file, &kmemleak_seq_ops); if (ret < 0) goto scan_unlock; @@ -1221,8 +1214,6 @@ static int kmemleak_open(struct inode *inode, struct file *file) scan_unlock: mutex_unlock(&scan_mutex); -kmemleak_unlock: - mutex_unlock(&kmemleak_mutex); out: return ret; } @@ -1231,11 +1222,9 @@ static int kmemleak_release(struct inode *inode, struct file *file) { int ret = 0; - if (file->f_mode & FMODE_READ) { + if (file->f_mode & FMODE_READ) seq_release(inode, file); - mutex_unlock(&scan_mutex); - } - mutex_unlock(&kmemleak_mutex); + mutex_unlock(&scan_mutex); return ret; } @@ -1250,6 +1239,7 @@ static int kmemleak_release(struct inode *inode, struct file *file) * scan=off - stop the automatic memory scanning thread * scan=... - set the automatic memory scanning period in seconds (0 to * disable it) + * scan - trigger a memory scan */ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, size_t size, loff_t *ppos) @@ -1287,7 +1277,9 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf, jiffies_scan_wait = msecs_to_jiffies(secs * 1000); start_scan_thread(); } - } else + } else if (strncmp(buf, "scan", 4) == 0) + kmemleak_scan(); + else return -EINVAL; /* ignore the rest of the buffer, only one command at a time */ @@ -1312,11 +1304,9 @@ static int kmemleak_cleanup_thread(void *arg) { struct kmemleak_object *object; - mutex_lock(&kmemleak_mutex); + mutex_lock(&scan_mutex); stop_scan_thread(); - mutex_unlock(&kmemleak_mutex); - mutex_lock(&scan_mutex); rcu_read_lock(); list_for_each_entry_rcu(object, &object_list, object_list) delete_object(object->pointer); @@ -1458,9 +1448,9 @@ static int __init kmemleak_late_init(void) &kmemleak_fops); if (!dentry) pr_warning("Failed to create the debugfs kmemleak file\n"); - mutex_lock(&kmemleak_mutex); + mutex_lock(&scan_mutex); start_scan_thread(); - mutex_unlock(&kmemleak_mutex); + mutex_unlock(&scan_mutex); pr_info("Kernel memory leak detector initialized\n"); -- GitLab From acf4968ec9dea49387ca8b3d36dfaa0850bdb2d5 Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Fri, 26 Jun 2009 17:38:29 +0100 Subject: [PATCH 0264/1002] kmemleak: Slightly change the policy on newly allocated objects Newly allocated objects are more likely to be reported as false positives. Kmemleak ignores the reporting of objects younger than 5 seconds. However, this age was calculated after the memory scanning completed which usually takes longer than 5 seconds. This patch make the minimum object age calculation in relation to the start of the memory scanning. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- mm/kmemleak.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index e96e0ec6a56eb..c37e8e50e4dee 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -190,7 +190,9 @@ static unsigned long max_addr; static unsigned long next_scan_yield; static struct task_struct *scan_thread; static unsigned long jiffies_scan_yield; +/* used to avoid reporting of recently allocated objects */ static unsigned long jiffies_min_age; +static unsigned long jiffies_last_scan; /* delay between automatic memory scannings */ static signed long jiffies_scan_wait; /* enables or disables the task stacks scanning */ @@ -284,7 +286,8 @@ static int color_gray(const struct kmemleak_object *object) static int unreferenced_object(struct kmemleak_object *object) { return (object->flags & OBJECT_ALLOCATED) && color_white(object) && - time_is_before_eq_jiffies(object->jiffies + jiffies_min_age); + time_before_eq(object->jiffies + jiffies_min_age, + jiffies_last_scan); } /* @@ -927,6 +930,8 @@ static void kmemleak_scan(void) int i; int new_leaks = 0; + jiffies_last_scan = jiffies; + /* prepare the kmemleak_object's */ rcu_read_lock(); list_for_each_entry_rcu(object, &object_list, object_list) { -- GitLab From 89bb871e96cdc3d78b7f69f0bacc94b21bbaccfd Mon Sep 17 00:00:00 2001 From: "Steven A. Falco" <sfalco@harris.com> Date: Fri, 26 Jun 2009 12:42:47 -0400 Subject: [PATCH 0265/1002] mtd: m25p80 timeout too short for worst-case m25p16 devices The m25p16 data sheet from numonyx lists the worst-case bulk erase time (tBE) as 40 seconds. Signed-off-by: Steven A. Falco <sfalco@harris.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/mtd/devices/m25p80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 59c46126a5ce3..ae5fe91867e15 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -54,7 +54,7 @@ #define SR_SRWD 0x80 /* SR write protect */ /* Define max times to check status register before we give up. */ -#define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */ +#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ #define CMD_SIZE 4 #ifdef CONFIG_M25PXX_USE_FAST_READ -- GitLab From 9c72ebef5aabf3532469d602a9d87beceea268b1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov <petkovbb@gmail.com> Date: Fri, 26 Jun 2009 11:22:37 -0700 Subject: [PATCH 0266/1002] ide-cd: handle fragmented packet commands gracefully There are some devices in the wild that clear the DRQ bit during the last word of a packet command and therefore could use a "second chance" for that last word of data to be xferred instead of simply failing the request. Do that by attempting to suck in those last bytes in PIO mode. In addition, the ATA_ERR bit has to be cleared for we cannot be sure the data is valid otherwise. See http://bugzilla.kernel.org/show_bug.cgi?id=13399 for details. Signed-off-by: Borislav Petkov <petkovbb@gmail.com> Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-cd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index f0ede5953af8b..6a9a769bffc19 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -592,9 +592,19 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } } else if (!blk_pc_request(rq)) { ide_cd_request_sense_fixup(drive, cmd); - /* complain if we still have data left to transfer */ + uptodate = cmd->nleft ? 0 : 1; - if (uptodate == 0) + + /* + * suck out the remaining bytes from the drive in an + * attempt to complete the data xfer. (see BZ#13399) + */ + if (!(stat & ATA_ERR) && !uptodate && thislen) { + ide_pio_bytes(drive, cmd, write, thislen); + uptodate = cmd->nleft ? 0 : 1; + } + + if (!uptodate) rq->cmd_flags |= REQ_FAILED; } goto out_end; -- GitLab From a32c7765e2796395aec49f699bd25c407155e9c5 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Fri, 26 Jun 2009 16:55:51 +0800 Subject: [PATCH 0267/1002] tracing: Fix stack tracer sysctl handling This made my machine completely frozen: # echo 1 > /proc/sys/kernel/stack_tracer_enabled # echo 2 > /proc/sys/kernel/stack_tracer_enabled The cause is register_ftrace_function() was called twice. Also fix ftrace_enabled sysctl, though seems nothing bad happened as I tested it. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <4A448D17.9010305@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/ftrace.c | 4 ++-- kernel/trace/trace_stack.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f3716bf04df64..bce9e01a29c84 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3160,10 +3160,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, ret = proc_dointvec(table, write, file, buffer, lenp, ppos); - if (ret || !write || (last_ftrace_enabled == ftrace_enabled)) + if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) goto out; - last_ftrace_enabled = ftrace_enabled; + last_ftrace_enabled = !!ftrace_enabled; if (ftrace_enabled) { diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 2d7aebd71dbd4..e644af9101246 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -326,10 +326,10 @@ stack_trace_sysctl(struct ctl_table *table, int write, ret = proc_dointvec(table, write, file, buffer, lenp, ppos); if (ret || !write || - (last_stack_tracer_enabled == stack_tracer_enabled)) + (last_stack_tracer_enabled == !!stack_tracer_enabled)) goto out; - last_stack_tracer_enabled = stack_tracer_enabled; + last_stack_tracer_enabled = !!stack_tracer_enabled; if (stack_tracer_enabled) register_ftrace_function(&trace_ops); -- GitLab From 82d5308127c3e3404ffbf41e503853c68660b18b Mon Sep 17 00:00:00 2001 From: Lai Jiangshan <laijs@cn.fujitsu.com> Date: Fri, 26 Jun 2009 17:07:02 +0800 Subject: [PATCH 0268/1002] trace_export: Repair missed fields Some fields for struct ftrace_graph_ret are missed when they are exported to user. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <4A448FB6.5000302@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_event_types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h index 5e32e375134d9..6db005e12487c 100644 --- a/kernel/trace/trace_event_types.h +++ b/kernel/trace/trace_event_types.h @@ -26,6 +26,9 @@ TRACE_EVENT_FORMAT(funcgraph_exit, TRACE_GRAPH_RET, ftrace_graph_ret_entry, ignore, TRACE_STRUCT( TRACE_FIELD(unsigned long, ret.func, func) + TRACE_FIELD(unsigned long long, ret.calltime, calltime) + TRACE_FIELD(unsigned long long, ret.rettime, rettime) + TRACE_FIELD(unsigned long, ret.overrun, overrun) TRACE_FIELD(int, ret.depth, depth) ), TP_RAW_FMT("<-- %lx (%d)") -- GitLab From 10e85448019097e4fcfa535f612f51d0d31a34f4 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Fri, 26 Jun 2009 10:46:08 +0000 Subject: [PATCH 0269/1002] decnet: Use rcu_barrier() on module unload. The decnet module unloading as been disabled with a '#if 0' statement, because it have had issues. We add a rcu_barrier() anyhow for correctness. The maintainer (Chrissie Caulfield) will look into the unload issue when time permits. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Chrissie Caulfield <christine.caulfield@googlemail.com> Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/decnet/af_decnet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index d351b8db0df5c..77d40289653cf 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2413,6 +2413,8 @@ static void __exit decnet_exit(void) proc_net_remove(&init_net, "decnet"); proto_unregister(&dn_proto); + + rcu_barrier_bh(); /* Wait for completion of call_rcu_bh()'s */ } module_exit(decnet_exit); #endif -- GitLab From 1f2ccd00f224a4e2d6d26f590f3e6851f3deef99 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Fri, 26 Jun 2009 10:46:03 +0000 Subject: [PATCH 0270/1002] ipv6: Use rcu_barrier() on module unload. The ipv6 module uses rcu_call() thus it should use rcu_barrier() on module unload. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv6/af_inet6.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 85b3d0036afde..caa0278d30a9d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -1284,6 +1284,8 @@ static void __exit inet6_exit(void) proto_unregister(&udplitev6_prot); proto_unregister(&udpv6_prot); proto_unregister(&tcpv6_prot); + + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } module_exit(inet6_exit); -- GitLab From 473c22d759e73cbbe604f41105b497817cc2ee8e Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Fri, 26 Jun 2009 10:45:48 +0000 Subject: [PATCH 0271/1002] bridge: Use rcu_barrier() instead of syncronize_net() on unload. When unloading modules that uses call_rcu() callbacks, then we must use rcu_barrier(). This module uses syncronize_net() which is not enough to be sure that all callback has been completed. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/bridge/br.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br.c b/net/bridge/br.c index 9aac5213105aa..e1241c76239a9 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -93,7 +93,7 @@ static void __exit br_deinit(void) unregister_pernet_subsys(&br_net_ops); - synchronize_net(); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ br_netfilter_fini(); #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) -- GitLab From 75de874f5c35f679c6370fccc2bf4930e638ef3b Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Fri, 26 Jun 2009 10:45:58 +0000 Subject: [PATCH 0272/1002] sunrpc: Use rcu_barrier() on unload. The sunrpc module uses rcu_call() thus it should use rcu_barrier() on module unload. Have not verified that the possibility for new call_rcu() callbacks has been disabled. As a hint for checking, the functions calling call_rcu() (unx_destroy_cred and generic_destroy_cred) are registered as crdestroy function pointer in struct rpc_credops. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/sunrpc/sunrpc_syms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 843629f557630..adaa81982f746 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -66,6 +66,7 @@ cleanup_sunrpc(void) #ifdef CONFIG_PROC_FS rpc_proc_exit(); #endif + rcu_barrier(); /* Wait for completion of call_rcu()'s */ } MODULE_LICENSE("GPL"); module_init(init_sunrpc); -- GitLab From 4a27096bbe2cad4c6e78802a0d9dfe0e598a1129 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer <hawk@comx.dk> Date: Fri, 26 Jun 2009 10:45:53 +0000 Subject: [PATCH 0273/1002] mac80211: Use rcu_barrier() on unload. The mac80211 module uses rcu_call() thus it should use rcu_barrier() on module unload. The rcu_barrier() is placed in mech.c ieee80211_stop_mesh() which is invoked from ieee80211_stop() in case vif.type == NL80211_IFTYPE_MESH_POINT. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/mac80211/mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index fc712e60705da..11cf45bce38a3 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -494,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) * should it be using the interface and enqueuing * frames at this very time on another CPU. */ - synchronize_rcu(); + rcu_barrier(); /* Wait for RX path and call_rcu()'s */ skb_queue_purge(&sdata->u.mesh.skb_queue); } -- GitLab From 73f1d9391a6aa72efdcea2f302ee7bfcd313c631 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Wed, 24 Jun 2009 01:04:36 +0900 Subject: [PATCH 0274/1002] asm-generic/vmlinux.lds.h: Fix up RW_DATA_SECTION definition. RW_DATA_SECTION is defined to take 4 different alignment parameters, while NOSAVE_DATA currently uses a fixed PAGE_SIZE alignment as noted in the comments. There are presently no in-tree users of this at present, and I just stumbled across this while implementing the simplified script on a new architecture port, which subsequently resulted in a syntax error. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- include/asm-generic/vmlinux.lds.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 92b73b6140ff4..f92e730695c83 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -704,7 +704,7 @@ * matches the requirment of PAGE_ALIGNED_DATA. * * use 0 as page_align if page_aligned data is not used */ -#define RW_DATA_SECTION(cacheline, nosave, pagealigned, inittask) \ +#define RW_DATA_SECTION(cacheline, pagealigned, inittask) \ . = ALIGN(PAGE_SIZE); \ .data : AT(ADDR(.data) - LOAD_OFFSET) { \ INIT_TASK(inittask) \ @@ -712,7 +712,7 @@ READ_MOSTLY_DATA(cacheline) \ DATA_DATA \ CONSTRUCTORS \ - NOSAVE_DATA(nosave) \ + NOSAVE_DATA \ PAGE_ALIGNED_DATA(pagealigned) \ } -- GitLab From d2af12aeadaedf657c9fb9c3df984d2c5ab25f4c Mon Sep 17 00:00:00 2001 From: Tim Abbott <tabbott@ksplice.com> Date: Tue, 23 Jun 2009 19:59:35 -0400 Subject: [PATCH 0275/1002] Add new macros for page-aligned data and bss sections. This patch is preparation for replacing most uses of ".bss.page_aligned" and ".data.page_aligned" in the kernel with macros, so that the section name can later be changed without having to touch a lot of the kernel. The long-term goal here is to be able to change the kernel's magic section names to those that are compatible with -ffunction-sections -fdata-sections. This requires renaming all magic sections with names of the form ".data.foo". Signed-off-by: Tim Abbott <tabbott@ksplice.com> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- include/linux/linkage.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/linkage.h b/include/linux/linkage.h index fee9e59649c12..691f59171c6c7 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -21,6 +21,15 @@ #define __page_aligned_data __section(.data.page_aligned) __aligned(PAGE_SIZE) #define __page_aligned_bss __section(.bss.page_aligned) __aligned(PAGE_SIZE) +/* + * For assembly routines. + * + * Note when using these that you must specify the appropriate + * alignment directives yourself + */ +#define __PAGE_ALIGNED_DATA .section ".data.page_aligned", "aw" +#define __PAGE_ALIGNED_BSS .section ".bss.page_aligned", "aw" + /* * This is used by architectures to keep arguments on the stack * untouched by the compiler by keeping them live until the end. -- GitLab From 39a449d96ac3db9b6d498b6ffbf4c763746d5e8b Mon Sep 17 00:00:00 2001 From: Tim Abbott <tabbott@ksplice.com> Date: Tue, 23 Jun 2009 18:53:15 -0400 Subject: [PATCH 0276/1002] asm-generic/vmlinux.lds.h: shuffle INIT_TASK* macro names in vmlinux.lds.h We recently added a INIT_TASK(align) in include/asm-generic/vmlinux.lds.h, but there is already a macro INIT_TASK in include/linux/init_task.h, which is quite confusing. We should switch the macro in the linker script to INIT_TASK_DATA. (Sorry that I missed this in reviewing the patch). Since the macros are new, there is only one user of the INIT_TASK in vmlinux.lds.h, arch/mn10300/kernel/vmlinux.lds.S. However, we are currently using INIT_TASK_DATA for laying down an entire .data.init_task section. So rename that to INIT_TASK_DATA_SECTION. I would be worried about changing the meaning of INIT_TASK_DATA, but the old INIT_TASK_DATA implementation had no users, and in fact if anyone had tried to use it, it would have failed to compile because it didn't pass the alignment to the old INIT_TASK. Signed-off-by: Tim Abbott <tabbott@ksplice.com> Cc: David Howells <dhowells@redhat.com> Cc: Jesper Nilsson <Jesper.Nilsson@axis.com Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- arch/mn10300/kernel/vmlinux.lds.S | 2 +- include/asm-generic/vmlinux.lds.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S index bcebcefb4ad7a..c96ba3da95ac1 100644 --- a/arch/mn10300/kernel/vmlinux.lds.S +++ b/arch/mn10300/kernel/vmlinux.lds.S @@ -61,7 +61,7 @@ SECTIONS _edata = .; /* End of data section */ } - .data.init_task : { INIT_TASK(THREAD_SIZE); } + .data.init_task : { INIT_TASK_DATA(THREAD_SIZE); } /* might get freed after init */ . = ALIGN(PAGE_SIZE); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f92e730695c83..720af4c722066 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -191,7 +191,7 @@ . = ALIGN(align); \ *(.data.cacheline_aligned) -#define INIT_TASK(align) \ +#define INIT_TASK_DATA(align) \ . = ALIGN(align); \ *(.data.init_task) @@ -434,10 +434,10 @@ /* * Init task */ -#define INIT_TASK_DATA(align) \ +#define INIT_TASK_DATA_SECTION(align) \ . = ALIGN(align); \ .data.init_task : { \ - INIT_TASK \ + INIT_TASK_DATA(align) \ } #ifdef CONFIG_CONSTRUCTORS @@ -707,7 +707,7 @@ #define RW_DATA_SECTION(cacheline, pagealigned, inittask) \ . = ALIGN(PAGE_SIZE); \ .data : AT(ADDR(.data) - LOAD_OFFSET) { \ - INIT_TASK(inittask) \ + INIT_TASK_DATA(inittask) \ CACHELINE_ALIGNED_DATA(cacheline) \ READ_MOSTLY_DATA(cacheline) \ DATA_DATA \ -- GitLab From 857eceebd2803c9a3459f784acf45e5266921e4d Mon Sep 17 00:00:00 2001 From: Tim Abbott <tabbott@ksplice.com> Date: Tue, 23 Jun 2009 19:59:36 -0400 Subject: [PATCH 0277/1002] Add new __init_task_data macro to be used in arch init_task.c files. This patch is preparation for replacing most ".data.init_task" in the kernel with macros, so that the section name can later be changed without having to touch a lot of the kernel. The long-term goal here is to be able to change the kernel's magic section names to those that are compatible with -ffunction-sections -fdata-sections. This requires renaming all magic sections with names of the form ".data.foo". Signed-off-by: Tim Abbott <tabbott@ksplice.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- include/linux/init_task.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 5368fbdc78018..7fc01b13be43c 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -183,5 +183,8 @@ extern struct cred init_cred; LIST_HEAD_INIT(cpu_timers[2]), \ } +/* Attach to the init_task data structure for proper alignment */ +#define __init_task_data __attribute__((__section__(".data.init_task"))) + #endif -- GitLab From 1ab18486e4e8bf9554d8439207b97422d7466d77 Mon Sep 17 00:00:00 2001 From: maximilian attems <max@stro.at> Date: Fri, 26 Jun 2009 20:04:36 +0200 Subject: [PATCH 0278/1002] kbuild: deb-pkg ship changelog In the series for 2.6.31 it was noticed to ship the copyright, but the generated changelog got lost somehow. As bonus the generated linux-image deb packages are Lenny lintian clean. Cc: Frans Pop <elendil@planet.nl> Cc: Andres Salomon <dilinger@debian.org> Signed-off-by: maximilian attems <max@stro.at> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- scripts/package/builddeb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 01c2d13dd0204..b19f1f4962e3d 100644 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -16,6 +16,8 @@ create_package() { local pname="$1" pdir="$2" cp debian/copyright "$pdir/usr/share/doc/$pname/" + cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian" + gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian" # Fix ownership and permissions chown -R root:root "$pdir" -- GitLab From 7a6b1f1c0c492a6bb6f778dff0f9f5facb90d1a1 Mon Sep 17 00:00:00 2001 From: Amerigo Wang <xiyou.wangcong@gmail.com> Date: Mon, 22 Jun 2009 17:18:32 +0800 Subject: [PATCH 0279/1002] gitignore: ignore gcov output files Ignore *.gcno files which are generated by gcov. Signed-off-by: WANG Cong <xiyou.wangcong@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cecb3b040cc17..b93fb7eff9428 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ *.gz *.lzma *.patch +*.gcno # # Top-level generic files -- GitLab From a8735821d198675dd326cc5847e79df79c735119 Mon Sep 17 00:00:00 2001 From: Floris Kraak <randakar@gmail.com> Date: Mon, 15 Jun 2009 08:54:02 +0300 Subject: [PATCH 0280/1002] Kbuild: Disable the -Wformat-security gcc flag Some distributions have enabled the gcc flag -Wformat-security by default. This results in a number of warnings about format arguments to functions, sometimes in cases where fixing the warning is not likely to actually fix a bug. Instead of hand patching a dozens of places (possibly more) that produce warnings that get ignored anyway we just turn off the flag in the Makefile. Signed-off-by: Floris Kraak <randakar@gmail.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d1216fea0c922..8fb9bfce212c1 100644 --- a/Makefile +++ b/Makefile @@ -344,7 +344,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ - -Werror-implicit-function-declaration + -Werror-implicit-function-declaration \ + -Wno-format-security KBUILD_AFLAGS := -D__ASSEMBLY__ # Read KERNELRELEASE from include/config/kernel.release (if it exists) -- GitLab From c512d2544c688ff1fab18a530860a9c7440a71b7 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Sat, 20 Jun 2009 18:25:25 +0530 Subject: [PATCH 0281/1002] gitignore: ignore scripts/ihex2fw scripts/ihex2fw is a generated binary and should be ignored Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- scripts/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/.gitignore b/scripts/.gitignore index b939fbd011953..52cab46ae35a3 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -7,3 +7,4 @@ pnmtologo bin2c unifdef binoffset +ihex2fw -- GitLab From 112942353992d95099fb5b71c679ff1046fccfcf Mon Sep 17 00:00:00 2001 From: Amerigo Wang <amwang@redhat.com> Date: Fri, 19 Jun 2009 03:40:26 -0400 Subject: [PATCH 0282/1002] kbuild: finally remove the obsolete variable $TOPDIR TOPDIR is obsolete, it can be finally removed now. Signed-off-by: WANG Cong <amwang@redhat.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> --- Makefile | 4 +--- drivers/scsi/cxgb3i/Kbuild | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 8fb9bfce212c1..b4c7ef5ab431d 100644 --- a/Makefile +++ b/Makefile @@ -140,15 +140,13 @@ _all: modules endif srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR)) -TOPDIR := $(srctree) -# FIXME - TOPDIR is obsolete, use srctree/objtree objtree := $(CURDIR) src := $(srctree) obj := $(objtree) VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) -export srctree objtree VPATH TOPDIR +export srctree objtree VPATH # SUBARCH tells the usermode build what the underlying arch is. That is set diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild index 25a2032bfa261..70d060b7ff4f6 100644 --- a/drivers/scsi/cxgb3i/Kbuild +++ b/drivers/scsi/cxgb3i/Kbuild @@ -1,4 +1,4 @@ -EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 +EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3 cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o -- GitLab From 71f9dacd2e4d233029e9e956ca3f79531f411827 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Fri, 26 Jun 2009 19:22:37 -0700 Subject: [PATCH 0283/1002] inet: Call skb_orphan before tproxy activates As transparent proxying looks up the socket early and assigns it to the skb for later processing, we must drop any existing socket ownership prior to that in order to distinguish between the case where tproxy is active and where it is not. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/ip_input.c | 3 +++ net/ipv6/ip6_input.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 490ce20faf38b..db46b4b5b2b94 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, /* Remove any debris in the socket control block */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); + /* Must drop socket now because of tproxy. */ + skb_orphan(skb); + return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c3a07d75b5f50..6d6a4277c6772 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt rcu_read_unlock(); + /* Must drop socket now because of tproxy. */ + skb_orphan(skb); + return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); err: -- GitLab From ff780cd8f2fa928b193554f593b36d1243554212 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Fri, 26 Jun 2009 19:27:04 -0700 Subject: [PATCH 0284/1002] gro: Flush GRO packets in napi_disable_pending path When NAPI is disabled while we're in net_rx_action, we end up calling __napi_complete without flushing GRO packets. This is a bug as it would cause the GRO packets to linger, of course it also literally BUGs to catch error like this :) This patch changes it to napi_complete, with the obligatory IRQ reenabling. This should be safe because we've only just disabled IRQs and it does not materially affect the test conditions in between. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/core/dev.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 60b5728122784..70c27e0c7c323 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2823,9 +2823,11 @@ static void net_rx_action(struct softirq_action *h) * move the instance around on the list at-will. */ if (unlikely(work == weight)) { - if (unlikely(napi_disable_pending(n))) - __napi_complete(n); - else + if (unlikely(napi_disable_pending(n))) { + local_irq_enable(); + napi_complete(n); + local_irq_disable(); + } else list_move_tail(&n->poll_list, list); } -- GitLab From fde953c1c67986e1c381fa50d8207b1578b5cefa Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Sat, 27 Jun 2009 06:06:39 +0200 Subject: [PATCH 0285/1002] perf_counter tools: Remove dead code Vince Weaver reported that there's a handful of #ifdef __MINGW32__ sections in the code. Remove them as they are in essence dead code - as unlike upstream Git, the perf tool is unlikely to be ported to Windows. Reported-by: Vince Weaver <vince@deater.net> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/help.c | 15 ------ tools/perf/util/pager.c | 5 +- tools/perf/util/run-command.c | 95 +---------------------------------- tools/perf/util/run-command.h | 5 -- tools/perf/util/util.h | 15 ------ 5 files changed, 3 insertions(+), 132 deletions(-) diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 6653f7dd1d784..17a00e0df2c49 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -126,21 +126,6 @@ static int is_executable(const char *name) !S_ISREG(st.st_mode)) return 0; -#ifdef __MINGW32__ - /* cannot trust the executable bit, peek into the file instead */ - char buf[3] = { 0 }; - int n; - int fd = open(name, O_RDONLY); - st.st_mode &= ~S_IXUSR; - if (fd >= 0) { - n = read(fd, buf, 2); - if (n == 2) - /* DOS executables start with "MZ" */ - if (!strcmp(buf, "#!") || !strcmp(buf, "MZ")) - st.st_mode |= S_IXUSR; - close(fd); - } -#endif return st.st_mode & S_IXUSR; } diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c index a28bccae5458b..1915de20dcacf 100644 --- a/tools/perf/util/pager.c +++ b/tools/perf/util/pager.c @@ -9,7 +9,6 @@ static int spawned_pager; -#ifndef __MINGW32__ static void pager_preexec(void) { /* @@ -24,7 +23,6 @@ static void pager_preexec(void) setenv("LESS", "FRSX", 0); } -#endif static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; static struct child_process pager_process; @@ -70,9 +68,8 @@ void setup_pager(void) pager_argv[2] = pager; pager_process.argv = pager_argv; pager_process.in = -1; -#ifndef __MINGW32__ pager_process.preexec_cb = pager_preexec; -#endif + if (start_command(&pager_process)) return; diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c index b2f5e854f40ad..a3935343091ab 100644 --- a/tools/perf/util/run-command.c +++ b/tools/perf/util/run-command.c @@ -65,7 +65,6 @@ int start_command(struct child_process *cmd) cmd->err = fderr[0]; } -#ifndef __MINGW32__ fflush(NULL); cmd->pid = fork(); if (!cmd->pid) { @@ -118,71 +117,6 @@ int start_command(struct child_process *cmd) } exit(127); } -#else - int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */ - const char **sargv = cmd->argv; - char **env = environ; - - if (cmd->no_stdin) { - s0 = dup(0); - dup_devnull(0); - } else if (need_in) { - s0 = dup(0); - dup2(fdin[0], 0); - } else if (cmd->in) { - s0 = dup(0); - dup2(cmd->in, 0); - } - - if (cmd->no_stderr) { - s2 = dup(2); - dup_devnull(2); - } else if (need_err) { - s2 = dup(2); - dup2(fderr[1], 2); - } - - if (cmd->no_stdout) { - s1 = dup(1); - dup_devnull(1); - } else if (cmd->stdout_to_stderr) { - s1 = dup(1); - dup2(2, 1); - } else if (need_out) { - s1 = dup(1); - dup2(fdout[1], 1); - } else if (cmd->out > 1) { - s1 = dup(1); - dup2(cmd->out, 1); - } - - if (cmd->dir) - die("chdir in start_command() not implemented"); - if (cmd->env) { - env = copy_environ(); - for (; *cmd->env; cmd->env++) - env = env_setenv(env, *cmd->env); - } - - if (cmd->perf_cmd) { - cmd->argv = prepare_perf_cmd(cmd->argv); - } - - cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env); - - if (cmd->env) - free_environ(env); - if (cmd->perf_cmd) - free(cmd->argv); - - cmd->argv = sargv; - if (s0 >= 0) - dup2(s0, 0), close(s0); - if (s1 >= 0) - dup2(s1, 1), close(s1); - if (s2 >= 0) - dup2(s2, 2), close(s2); -#endif if (cmd->pid < 0) { int err = errno; @@ -288,14 +222,6 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const return run_command(&cmd); } -#ifdef __MINGW32__ -static __stdcall unsigned run_thread(void *data) -{ - struct async *async = data; - return async->proc(async->fd_for_proc, async->data); -} -#endif - int start_async(struct async *async) { int pipe_out[2]; @@ -304,7 +230,6 @@ int start_async(struct async *async) return error("cannot create pipe: %s", strerror(errno)); async->out = pipe_out[0]; -#ifndef __MINGW32__ /* Flush stdio before fork() to avoid cloning buffers */ fflush(NULL); @@ -319,33 +244,17 @@ int start_async(struct async *async) exit(!!async->proc(pipe_out[1], async->data)); } close(pipe_out[1]); -#else - async->fd_for_proc = pipe_out[1]; - async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL); - if (!async->tid) { - error("cannot create thread: %s", strerror(errno)); - close_pair(pipe_out); - return -1; - } -#endif + return 0; } int finish_async(struct async *async) { -#ifndef __MINGW32__ int ret = 0; if (wait_or_whine(async->pid)) ret = error("waitpid (async) failed"); -#else - DWORD ret = 0; - if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0) - ret = error("waiting for thread failed: %lu", GetLastError()); - else if (!GetExitCodeThread(async->tid, &ret)) - ret = error("cannot get thread exit code: %lu", GetLastError()); - CloseHandle(async->tid); -#endif + return ret; } diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h index 328289f236695..cc1837deba88a 100644 --- a/tools/perf/util/run-command.h +++ b/tools/perf/util/run-command.h @@ -79,12 +79,7 @@ struct async { int (*proc)(int fd, void *data); void *data; int out; /* caller reads from here and closes it */ -#ifndef __MINGW32__ pid_t pid; -#else - HANDLE tid; - int fd_for_proc; -#endif }; int start_async(struct async *async); diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b8cfed776d818..b4be6071c1057 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -67,7 +67,6 @@ #include <assert.h> #include <regex.h> #include <utime.h> -#ifndef __MINGW32__ #include <sys/wait.h> #include <sys/poll.h> #include <sys/socket.h> @@ -81,20 +80,6 @@ #include <netdb.h> #include <pwd.h> #include <inttypes.h> -#if defined(__CYGWIN__) -#undef _XOPEN_SOURCE -#include <grp.h> -#define _XOPEN_SOURCE 600 -#include "compat/cygwin.h" -#else -#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */ -#include <grp.h> -#define _ALL_SOURCE 1 -#endif -#else /* __MINGW32__ */ -/* pull in Windows compatibility stuff */ -#include "compat/mingw.h" -#endif /* __MINGW32__ */ #ifndef NO_ICONV #include <iconv.h> -- GitLab From 0cfb7a13b8e4e0afd4b856156ab16a182de7505b Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Sat, 27 Jun 2009 06:10:30 +0200 Subject: [PATCH 0286/1002] perf stat: Add -n/--null option to run without counters Allow a no-counters run. This can be useful to measure just elapsed wall-clock time - or to assess the raw overhead of perf stat itself, without running any counters. Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8420ec589506f..cdcd058fac08b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -70,6 +70,7 @@ static int run_count = 1; static int inherit = 1; static int scale = 1; static int target_pid = -1; +static int null_run = 0; static int fd[MAX_NR_CPUS][MAX_COUNTERS]; @@ -461,6 +462,8 @@ static const struct option options[] = { "be more verbose (show counter open errors, etc)"), OPT_INTEGER('r', "repeat", &run_count, "repeat command and print average + stddev (max: 100)"), + OPT_BOOLEAN('n', "null", &null_run, + "null run - dont start any counters"), OPT_END() }; @@ -476,7 +479,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix) if (run_count <= 0 || run_count > MAX_RUN) usage_with_options(stat_usage, options); - if (!nr_counters) + if (!null_run && !nr_counters) nr_counters = 8; nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); -- GitLab From 566747e6298289c5cb02d4939cb3abf1c4fe7e5a Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Sat, 27 Jun 2009 06:24:32 +0200 Subject: [PATCH 0287/1002] perf stat: Fix multi-run stats In multi-run (-r/--repeat) printouts, print out the noise of the wall-clock average as well. Also, fix a bug in printing out scaled counters: if it was not scaled then we should not update the average with -1. Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index cdcd058fac08b..52c176cc683ec 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -353,8 +353,11 @@ static void calc_avg(void) event_res_avg[j]+1, event_res[i][j]+1); update_avg("counter/2", j, event_res_avg[j]+2, event_res[i][j]+2); - update_avg("scaled", j, - event_scaled_avg + j, event_scaled[i]+j); + if (event_scaled[i][j] != -1) + update_avg("scaled", j, + event_scaled_avg + j, event_scaled[i]+j); + else + event_scaled_avg[j] = -1; } } runtime_nsecs_avg /= run_count; @@ -420,9 +423,13 @@ static void print_stat(int argc, const char **argv) fprintf(stderr, "\n"); - fprintf(stderr, " %14.9f seconds time elapsed.\n", + fprintf(stderr, " %14.9f seconds time elapsed", (double)walltime_nsecs_avg/1e9); - fprintf(stderr, "\n"); + if (run_count > 1) { + fprintf(stderr, " ( +- %7.3f%% )", + 100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg); + } + fprintf(stderr, "\n\n"); } static volatile int signr = -1; -- GitLab From 70ec3bb8ea3f8c55b255f41d122c7d4d8c0d00b4 Mon Sep 17 00:00:00 2001 From: Julia Lawall <julia@diku.dk> Date: Sat, 27 Jun 2009 09:55:32 +0200 Subject: [PATCH 0288/1002] mtd: Use BLOCK_NIL consistently in NFTL/INFTL Use BLOCK_NIL consistently rather than sometimes 0xffff and sometimes BLOCK_NIL. The semantic patch that finds this issue is below (http://www.emn.fr/x-info/coccinelle/). On the other hand, the changes were made by hand, in part because drivers/mtd/inftlcore.c contains dead code that causes spatch to ignore a relevant function. Specifically, the function INFTL_findwriteunit contains a do-while loop, but always takes a return that leaves the loop on the first iteration. // <smpl> @r exists@ identifier f,C; @@ f(...) { ... return C; } @s@ identifier r.C; expression E; @@ @@ identifier r.f,r.C,I; expression s.E; @@ f(...) { <... ( I | - E + C ) ...> } // </smpl> Signed-off-by: Julia Lawall <julia@diku.dk> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/mtd/inftlcore.c | 11 ++++++----- drivers/mtd/nftlcore.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 73f05227dc8cb..d8cf29c01cc46 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -226,7 +226,7 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) if (!desperate && inftl->numfreeEUNs < 2) { DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free " "EUNs (%d)\n", inftl->numfreeEUNs); - return 0xffff; + return BLOCK_NIL; } /* Scan for a free block */ @@ -281,7 +281,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned silly = MAX_LOOPS; while (thisEUN < inftl->nb_blocks) { for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { - if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) + if ((BlockMap[block] != BLOCK_NIL) || + BlockDeleted[block]) continue; if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) @@ -525,7 +526,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) if (!silly--) { printk(KERN_WARNING "INFTL: infinite loop in " "Virtual Unit Chain 0x%x\n", thisVUC); - return 0xffff; + return BLOCK_NIL; } /* Skip to next block in chain */ @@ -549,7 +550,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) * waiting to be picked up. We're going to have to fold * a chain to make room. */ - thisEUN = INFTL_makefreeblock(inftl, 0xffff); + thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL); /* * Hopefully we free something, lets try again. @@ -631,7 +632,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) printk(KERN_WARNING "INFTL: error folding to make room for Virtual " "Unit Chain 0x%x\n", thisVUC); - return 0xffff; + return BLOCK_NIL; } /* diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e3f8495a94c27..fb86cacd5bdb6 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -208,7 +208,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) /* Normally, we force a fold to happen before we run out of free blocks completely */ if (!desperate && nftl->numfreeEUNs < 2) { DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); - return 0xffff; + return BLOCK_NIL; } /* Scan for a free block */ @@ -230,11 +230,11 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) printk("Argh! No free blocks found! LastFreeEUN = %d, " "FirstEUN = %d\n", nftl->LastFreeEUN, le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); - return 0xffff; + return BLOCK_NIL; } } while (pot != nftl->LastFreeEUN); - return 0xffff; + return BLOCK_NIL; } static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) @@ -431,7 +431,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p /* add the header so that it is now a valid chain */ oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL; nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, 8, &retlen, (char *)&oob.u); @@ -515,7 +515,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) if (ChainLength < 2) { printk(KERN_WARNING "No Virtual Unit Chains available for folding. " "Failing request\n"); - return 0xffff; + return BLOCK_NIL; } return NFTL_foldchain (nftl, LongestChain, pendingblock); @@ -578,7 +578,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); - return 0xffff; + return BLOCK_NIL; } /* Skip to next block in chain */ @@ -601,7 +601,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) //u16 startEUN = nftl->EUNtable[thisVUC]; //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); - writeEUN = NFTL_makefreeblock(nftl, 0xffff); + writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL); if (writeEUN == BLOCK_NIL) { /* OK, we accept that the above comment is @@ -673,7 +673,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", thisVUC); - return 0xffff; + return BLOCK_NIL; } static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, -- GitLab From 702b59e623c3ca80beaeab79ca5ede4ea23170e2 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Fri, 26 Jun 2009 21:36:36 +0100 Subject: [PATCH 0289/1002] [ARM] 5573/1: ep93xx: ensure typesafe io ARM: ep93xx: ensure typesafe io For the ep93xx platform, all EP93XX_*_BASE defines are based on virtual addresses. Ensure that all these defines are properly typesafe for the __raw_{read/write}* macros. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../mach-ep93xx/include/mach/ep93xx-regs.h | 61 ++++++++++--------- arch/arm/mach-ep93xx/include/mach/io.h | 17 +++++- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 967c079180dbc..49b256b3ddfc2 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -52,40 +52,43 @@ #define EP93XX_AHB_VIRT_BASE 0xfef00000 #define EP93XX_AHB_SIZE 0x00100000 +#define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x)) + #define EP93XX_APB_PHYS_BASE 0x80800000 #define EP93XX_APB_VIRT_BASE 0xfed00000 #define EP93XX_APB_SIZE 0x00200000 +#define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x)) + /* AHB peripherals */ -#define EP93XX_DMA_BASE ((void __iomem *) \ - (EP93XX_AHB_VIRT_BASE + 0x00000000)) +#define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000) -#define EP93XX_ETHERNET_BASE (EP93XX_AHB_VIRT_BASE + 0x00010000) #define EP93XX_ETHERNET_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00010000) +#define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000) -#define EP93XX_USB_BASE (EP93XX_AHB_VIRT_BASE + 0x00020000) #define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) +#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) -#define EP93XX_RASTER_BASE (EP93XX_AHB_VIRT_BASE + 0x00030000) +#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) -#define EP93XX_GRAPHICS_ACCEL_BASE (EP93XX_AHB_VIRT_BASE + 0x00040000) +#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) -#define EP93XX_SDRAM_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00060000) +#define EP93XX_SDRAM_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00060000) -#define EP93XX_PCMCIA_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00080000) +#define EP93XX_PCMCIA_CONTROLLER_BASE EP93XX_AHB_IOMEM(0x00080000) -#define EP93XX_BOOT_ROM_BASE (EP93XX_AHB_VIRT_BASE + 0x00090000) +#define EP93XX_BOOT_ROM_BASE EP93XX_AHB_IOMEM(0x00090000) -#define EP93XX_IDE_BASE (EP93XX_AHB_VIRT_BASE + 0x000a0000) +#define EP93XX_IDE_BASE EP93XX_AHB_IOMEM(0x000a0000) -#define EP93XX_VIC1_BASE (EP93XX_AHB_VIRT_BASE + 0x000b0000) +#define EP93XX_VIC1_BASE EP93XX_AHB_IOMEM(0x000b0000) -#define EP93XX_VIC2_BASE (EP93XX_AHB_VIRT_BASE + 0x000c0000) +#define EP93XX_VIC2_BASE EP93XX_AHB_IOMEM(0x000c0000) /* APB peripherals */ -#define EP93XX_TIMER_BASE (EP93XX_APB_VIRT_BASE + 0x00010000) +#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) #define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) #define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) #define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) @@ -102,11 +105,11 @@ #define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) #define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) -#define EP93XX_I2S_BASE (EP93XX_APB_VIRT_BASE + 0x00020000) +#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) -#define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000) +#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) -#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) +#define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) #define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c) #define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50) @@ -124,32 +127,32 @@ #define EP93XX_GPIO_B_INT_ENABLE EP93XX_GPIO_REG(0xb8) #define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) -#define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) +#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) -#define EP93XX_SPI_BASE (EP93XX_APB_VIRT_BASE + 0x000a0000) +#define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000) -#define EP93XX_IRDA_BASE (EP93XX_APB_VIRT_BASE + 0x000b0000) +#define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000) -#define EP93XX_UART1_BASE (EP93XX_APB_VIRT_BASE + 0x000c0000) #define EP93XX_UART1_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000c0000) +#define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000) -#define EP93XX_UART2_BASE (EP93XX_APB_VIRT_BASE + 0x000d0000) #define EP93XX_UART2_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000d0000) +#define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000) -#define EP93XX_UART3_BASE (EP93XX_APB_VIRT_BASE + 0x000e0000) #define EP93XX_UART3_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000e0000) +#define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000) -#define EP93XX_KEY_MATRIX_BASE (EP93XX_APB_VIRT_BASE + 0x000f0000) +#define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000) -#define EP93XX_ADC_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) -#define EP93XX_TOUCHSCREEN_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) +#define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000) +#define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000) -#define EP93XX_PWM_BASE (EP93XX_APB_VIRT_BASE + 0x00110000) +#define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000) -#define EP93XX_RTC_BASE (EP93XX_APB_VIRT_BASE + 0x00120000) #define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000) +#define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000) -#define EP93XX_SYSCON_BASE (EP93XX_APB_VIRT_BASE + 0x00130000) +#define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000) #define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x)) #define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00) #define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04) @@ -179,7 +182,7 @@ #define EP93XX_SYSCON_DEVICE_CONFIG_U1EN (1<<18) #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) -#define EP93XX_WATCHDOG_BASE (EP93XX_APB_VIRT_BASE + 0x00140000) +#define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) #endif diff --git a/arch/arm/mach-ep93xx/include/mach/io.h b/arch/arm/mach-ep93xx/include/mach/io.h index fd5f081cc8b72..cebcc1c53d63e 100644 --- a/arch/arm/mach-ep93xx/include/mach/io.h +++ b/arch/arm/mach-ep93xx/include/mach/io.h @@ -1,8 +1,21 @@ /* * arch/arm/mach-ep93xx/include/mach/io.h */ +#ifndef __ASM_MACH_IO_H +#define __ASM_MACH_IO_H #define IO_SPACE_LIMIT 0xffffffff -#define __io(p) __typesafe_io(p) -#define __mem_pci(p) (p) +#define __io(p) __typesafe_io(p) +#define __mem_pci(p) (p) + +/* + * A typesafe __io() variation for variable initialisers + */ +#ifdef __ASSEMBLER__ +#define IOMEM(p) p +#else +#define IOMEM(p) ((void __iomem __force *)(p)) +#endif + +#endif /* __ASM_MACH_IO_H */ -- GitLab From ddf4f3d994651ee2924432a618d9caefed411dc1 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Fri, 26 Jun 2009 21:39:27 +0100 Subject: [PATCH 0290/1002] [ARM] 5574/1: ep93xx: gpio.c: fix header includes and __iomem pointers Fix ep93xx gpio.c header includes and __iomem pointers. 1. <linux/gpio.h> should be included instead of <asm/gpio.h> 2. <mach/hardware.h> should be included instead of <mach/ep93xx-regs.h> 3. data_reg and data_dir_reg in struct ep93xx_gpio_chip should be void __iomem pointers not unsigned int Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/gpio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 482cf3d2fbcd5..7b7a564916f38 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -17,15 +17,15 @@ #include <linux/module.h> #include <linux/seq_file.h> #include <linux/io.h> +#include <linux/gpio.h> -#include <mach/ep93xx-regs.h> -#include <asm/gpio.h> +#include <mach/hardware.h> struct ep93xx_gpio_chip { struct gpio_chip chip; - unsigned int data_reg; - unsigned int data_dir_reg; + void __iomem *data_reg; + void __iomem *data_dir_reg; }; #define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) -- GitLab From f04989bbf4a40077dc7ddcc3dccde11a5f3e91f2 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Fri, 26 Jun 2009 21:40:34 +0100 Subject: [PATCH 0291/1002] [ARM] 5575/1: ep93xx: Show gpio interrupt type in debugfs output. ep93xx: Show gpio interrupt type in debugfs output. EP93xx uses a private implementation for the debugfs output. Modify this output so it includes the interrupt type when the gpio is configured as an interrupt Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/gpio.c | 56 +++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 7b7a564916f38..2d83d69e2eed0 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -111,15 +111,61 @@ static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); u8 data_reg, data_dir_reg; - int i; + int gpio, i; data_reg = __raw_readb(ep93xx_chip->data_reg); data_dir_reg = __raw_readb(ep93xx_chip->data_dir_reg); - for (i = 0; i < chip->ngpio; i++) - seq_printf(s, "GPIO %s%d: %s %s\n", chip->label, i, - (data_reg & (1 << i)) ? "set" : "clear", - (data_dir_reg & (1 << i)) ? "out" : "in"); + gpio = ep93xx_chip->chip.base; + for (i = 0; i < chip->ngpio; i++, gpio++) { + int is_out = data_dir_reg & (1 << i); + + seq_printf(s, " %s%d gpio-%-3d (%-12s) %s %s", + chip->label, i, gpio, + gpiochip_is_requested(chip, i) ? : "", + is_out ? "out" : "in ", + (data_reg & (1 << i)) ? "hi" : "lo"); + + if (!is_out) { + int irq = gpio_to_irq(gpio); + struct irq_desc *desc = irq_desc + irq; + + if (irq >= 0 && desc->action) { + char *trigger; + + switch (desc->status & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_NONE: + trigger = "(default)"; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger = "edge-falling"; + break; + case IRQ_TYPE_EDGE_RISING: + trigger = "edge-rising"; + break; + case IRQ_TYPE_EDGE_BOTH: + trigger = "edge-both"; + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger = "level-high"; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger = "level-low"; + break; + default: + trigger = "?trigger?"; + break; + } + + seq_printf(s, " irq-%d %s%s", + irq, trigger, + (desc->status & IRQ_WAKEUP) + ? " wakeup" : ""); + } + } + + seq_printf(s, "\n"); + } } #define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \ -- GitLab From 9a24ee03aebc55cec00cc388b6727bff24ed433f Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Wed, 24 Jun 2009 17:13:48 +0100 Subject: [PATCH 0292/1002] [ARM] 5563/1: at91: at91sam9rlek lcd interface correction Here is a little update to the at91sam9rlek lcd interface. This will correct the power pin of the LCD. It will also add precision to the struct atmel_lcdfb_info scructure: backlight enabling and wiring mode correction: RGB wiring on the -EK board. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-sam9rlek.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 35e12a49d1a68..f6b5672cabd63 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -186,19 +186,21 @@ static struct fb_monspecs at91fb_default_monspecs = { static void at91_lcdc_power_control(int on) { if (on) - at91_set_gpio_value(AT91_PIN_PA30, 0); /* power up */ + at91_set_gpio_value(AT91_PIN_PC1, 0); /* power up */ else - at91_set_gpio_value(AT91_PIN_PA30, 1); /* power down */ + at91_set_gpio_value(AT91_PIN_PC1, 1); /* power down */ } /* Driver datas */ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { + .lcdcon_is_backlight = true, .default_bpp = 16, .default_dmacon = ATMEL_LCDC_DMAEN, .default_lcdcon2 = AT91SAM9RL_DEFAULT_LCDCON2, .default_monspecs = &at91fb_default_monspecs, .atmel_lcdfb_power_control = at91_lcdc_power_control, .guard_time = 1, + .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, }; #else -- GitLab From 226ddb9833a3c2f1087bfac70659d8e318d3c31f Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Wed, 24 Jun 2009 17:13:47 +0100 Subject: [PATCH 0293/1002] [ARM] 5564/1: at91: add gpio button and leds support for at91sam9rlek This adds input keyboard gpio support on at91sam9rlek board. It adds button 1 and 2 (left and right click). It also adds gpio leds ds1, ds2 and ds3. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-sam9rlek.c | 79 +++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 35e12a49d1a68..9120d5d3a6fc3 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -15,6 +15,8 @@ #include <linux/spi/spi.h> #include <linux/fb.h> #include <linux/clk.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> #include <video/atmel_lcdc.h> @@ -206,6 +208,79 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data; #endif +/* + * LEDs + */ +static struct gpio_led ek_leds[] = { + { /* "bottom" led, green, userled1 to be defined */ + .name = "ds1", + .gpio = AT91_PIN_PD15, + .active_low = 1, + .default_trigger = "none", + }, + { /* "bottom" led, green, userled2 to be defined */ + .name = "ds2", + .gpio = AT91_PIN_PD16, + .active_low = 1, + .default_trigger = "none", + }, + { /* "power" led, yellow */ + .name = "ds3", + .gpio = AT91_PIN_PD14, + .default_trigger = "heartbeat", + } +}; + + +/* + * GPIO Buttons + */ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button ek_buttons[] = { + { + .gpio = AT91_PIN_PB0, + .code = BTN_2, + .desc = "Right Click", + .active_low = 1, + .wakeup = 1, + }, + { + .gpio = AT91_PIN_PB1, + .code = BTN_1, + .desc = "Left Click", + .active_low = 1, + .wakeup = 1, + } +}; + +static struct gpio_keys_platform_data ek_button_data = { + .buttons = ek_buttons, + .nbuttons = ARRAY_SIZE(ek_buttons), +}; + +static struct platform_device ek_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &ek_button_data, + } +}; + +static void __init ek_add_device_buttons(void) +{ + at91_set_gpio_input(AT91_PIN_PB1, 1); /* btn1 */ + at91_set_deglitch(AT91_PIN_PB1, 1); + at91_set_gpio_input(AT91_PIN_PB0, 1); /* btn2 */ + at91_set_deglitch(AT91_PIN_PB0, 1); + + platform_device_register(&ek_button_device); +} +#else +static void __init ek_add_device_buttons(void) {} +#endif + + static void __init ek_board_init(void) { /* Serial */ @@ -224,6 +299,10 @@ static void __init ek_board_init(void) at91_add_device_lcdc(&ek_lcdc_data); /* Touch Screen Controller */ at91_add_device_tsadcc(); + /* LEDs */ + at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); + /* Push Buttons */ + ek_add_device_buttons(); } MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK") -- GitLab From 7c6425a0404399ba78852ef4108007ecf51ef3dc Mon Sep 17 00:00:00 2001 From: Ryan Mallon <ryan@bluewatersys.com> Date: Wed, 24 Jun 2009 23:15:23 +0100 Subject: [PATCH 0294/1002] [ARM] 5566/1: Remove at91_gpiolib_request Remove at91_gpiolib_request. It returns -EPERM if a request pin is not in GPIO mode, however we want to be able to gpio_request alternative function pins to reserve them, and in some cases we need to be able to use the gpiolib functions on alternative function pins. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/gpio.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index f2236f0e101f6..ae4772e744ac4 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -44,13 +44,11 @@ static int at91_gpiolib_direction_output(struct gpio_chip *chip, unsigned offset, int val); static int at91_gpiolib_direction_input(struct gpio_chip *chip, unsigned offset); -static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset); #define AT91_GPIO_CHIP(name, base_gpio, nr_gpio) \ { \ .chip = { \ .label = name, \ - .request = at91_gpiolib_request, \ .direction_input = at91_gpiolib_direction_input, \ .direction_output = at91_gpiolib_direction_output, \ .get = at91_gpiolib_get, \ @@ -588,19 +586,6 @@ static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val) __raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR)); } -static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset) -{ - unsigned pin = chip->base + offset; - void __iomem *pio = pin_to_controller(pin); - unsigned mask = pin_to_mask(pin); - - /* Cannot request GPIOs that are in alternate function mode */ - if (!(__raw_readl(pio + PIO_PSR) & mask)) - return -EPERM; - - return 0; -} - static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) { int i; -- GitLab From 2ef9df7ada6b6dd53446a994ef6e3a6ad5a300ef Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:36:57 +0100 Subject: [PATCH 0295/1002] [ARM] 5569/1: at91: Support for at91sam9g45: clocks management Add the at91sam9g45 series support to the AT91 generic clock file. This takes care of the particularities of the PMC for this series. It also takes advantage of the management by functionalities of those PLLs and clocks. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/clock.c | 62 ++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index bac578fe0d3d3..6396680271e85 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -47,20 +47,25 @@ * Chips have some kind of clocks : group them by functionality */ #define cpu_has_utmi() ( cpu_is_at91cap9() \ - || cpu_is_at91sam9rl()) + || cpu_is_at91sam9rl() \ + || cpu_is_at91sam9g45()) -#define cpu_has_800M_plla() (cpu_is_at91sam9g20()) +#define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ + || cpu_is_at91sam9g45()) -#define cpu_has_pllb() (!cpu_is_at91sam9rl()) +#define cpu_has_300M_plla() (0) -#define cpu_has_upll() (0) +#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ + || cpu_is_at91sam9g45())) + +#define cpu_has_upll() (cpu_is_at91sam9g45()) /* USB host HS & FS */ #define cpu_has_uhp() (!cpu_is_at91sam9rl()) /* USB device FS only */ -#define cpu_has_udpfs() (!cpu_is_at91sam9rl()) - +#define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \ + || cpu_is_at91sam9g45())) static LIST_HEAD(clocks); static DEFINE_SPINLOCK(clk_lock); @@ -133,6 +138,13 @@ static void pmc_uckr_mode(struct clk *clk, int is_on) { unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR); + if (cpu_is_at91sam9g45()) { + if (is_on) + uckr |= AT91_PMC_BIASEN; + else + uckr &= ~AT91_PMC_BIASEN; + } + if (is_on) { is_on = AT91_PMC_LOCKU; at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask); @@ -310,6 +322,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) unsigned long flags; unsigned prescale; unsigned long actual; + unsigned long prev = ULONG_MAX; if (!clk_is_programmable(clk)) return -EINVAL; @@ -317,8 +330,16 @@ long clk_round_rate(struct clk *clk, unsigned long rate) actual = clk->parent->rate_hz; for (prescale = 0; prescale < 7; prescale++) { - if (actual && actual <= rate) + if (actual > rate) + prev = actual; + + if (actual && actual <= rate) { + if ((prev - rate) < (rate - actual)) { + actual = prev; + prescale--; + } break; + } actual >>= 1; } @@ -373,6 +394,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent) return -EBUSY; if (!clk_is_primary(parent) || !clk_is_programmable(clk)) return -EINVAL; + + if (cpu_is_at91sam9rl() && parent->id == AT91_PMC_CSS_PLLB) + return -EINVAL; + spin_lock_irqsave(&clk_lock, flags); clk->rate_hz = parent->rate_hz; @@ -637,6 +662,7 @@ int __init at91_clock_init(unsigned long main_clock) { unsigned tmp, freq, mckr; int i; + int pll_overclock = false; /* * When the bootloader initialized the main oscillator correctly, @@ -654,12 +680,25 @@ int __init at91_clock_init(unsigned long main_clock) /* report if PLLA is more than mildly overclocked */ plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR)); - if ((!cpu_has_800M_plla() && plla.rate_hz > 209000000) - || (cpu_has_800M_plla() && plla.rate_hz > 800000000)) + if (cpu_has_300M_plla()) { + if (plla.rate_hz > 300000000) + pll_overclock = true; + } else if (cpu_has_800M_plla()) { + if (plla.rate_hz > 800000000) + pll_overclock = true; + } else { + if (plla.rate_hz > 209000000) + pll_overclock = true; + } + if (pll_overclock) pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); + if (cpu_is_at91sam9g45()) { + mckr = at91_sys_read(AT91_PMC_MCKR); + plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12)); /* plla divisor by 2 */ + } - if (cpu_has_upll() && !cpu_has_pllb()) { + if (!cpu_has_pllb() && cpu_has_upll()) { /* setup UTMI clock as the fourth primary clock * (instead of pllb) */ utmi_clk.type |= CLK_TYPE_PRIMARY; @@ -701,6 +740,9 @@ int __init at91_clock_init(unsigned long main_clock) freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ if (mckr & AT91_PMC_PDIV) freq /= 2; /* processor clock division */ + } else if (cpu_is_at91sam9g45()) { + mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ? + freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ } else { mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ } -- GitLab From fddcc0ae58edefeb7ac1e460411d7dfbe8ebdacc Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:36:56 +0100 Subject: [PATCH 0296/1002] [ARM] 5571/1: at91: Basic support for at91sam9g45 series: header files. AT91sam9g45 series is an ARM 926ej-s SOC family clocked at 400/133MHz. It embedds USB high speed host and device, LCD, DDR2 RAM, and a full set of peripherals. Here is the basic header file support for this product series. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/include/mach/at91sam9g45.h | 138 ++++++++++++++++ .../include/mach/at91sam9g45_matrix.h | 153 ++++++++++++++++++ arch/arm/mach-at91/include/mach/cpu.h | 16 ++ arch/arm/mach-at91/include/mach/hardware.h | 2 + arch/arm/mach-at91/include/mach/timex.h | 5 + 5 files changed, 314 insertions(+) create mode 100644 arch/arm/mach-at91/include/mach/at91sam9g45.h create mode 100644 arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h new file mode 100644 index 0000000000000..2c42cf5f0c549 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h @@ -0,0 +1,138 @@ +/* + * Chip-specific header file for the AT91SAM9G45 family + * + * Copyright (C) 2008-2009 Atmel Corporation. + * + * Common definitions. + * Based on AT91SAM9G45 preliminary datasheet. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91SAM9G45_H +#define AT91SAM9G45_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Controller Interrupt */ +#define AT91SAM9G45_ID_PIOA 2 /* Parallel I/O Controller A */ +#define AT91SAM9G45_ID_PIOB 3 /* Parallel I/O Controller B */ +#define AT91SAM9G45_ID_PIOC 4 /* Parallel I/O Controller C */ +#define AT91SAM9G45_ID_PIODE 5 /* Parallel I/O Controller D and E */ +#define AT91SAM9G45_ID_TRNG 6 /* True Random Number Generator */ +#define AT91SAM9G45_ID_US0 7 /* USART 0 */ +#define AT91SAM9G45_ID_US1 8 /* USART 1 */ +#define AT91SAM9G45_ID_US2 9 /* USART 2 */ +#define AT91SAM9G45_ID_US3 10 /* USART 3 */ +#define AT91SAM9G45_ID_MCI0 11 /* High Speed Multimedia Card Interface 0 */ +#define AT91SAM9G45_ID_TWI0 12 /* Two-Wire Interface 0 */ +#define AT91SAM9G45_ID_TWI1 13 /* Two-Wire Interface 1 */ +#define AT91SAM9G45_ID_SPI0 14 /* Serial Peripheral Interface 0 */ +#define AT91SAM9G45_ID_SPI1 15 /* Serial Peripheral Interface 1 */ +#define AT91SAM9G45_ID_SSC0 16 /* Synchronous Serial Controller 0 */ +#define AT91SAM9G45_ID_SSC1 17 /* Synchronous Serial Controller 1 */ +#define AT91SAM9G45_ID_TCB 18 /* Timer Counter 0, 1, 2, 3, 4 and 5 */ +#define AT91SAM9G45_ID_PWMC 19 /* Pulse Width Modulation Controller */ +#define AT91SAM9G45_ID_TSC 20 /* Touch Screen ADC Controller */ +#define AT91SAM9G45_ID_DMA 21 /* DMA Controller */ +#define AT91SAM9G45_ID_UHPHS 22 /* USB Host High Speed */ +#define AT91SAM9G45_ID_LCDC 23 /* LCD Controller */ +#define AT91SAM9G45_ID_AC97C 24 /* AC97 Controller */ +#define AT91SAM9G45_ID_EMAC 25 /* Ethernet MAC */ +#define AT91SAM9G45_ID_ISI 26 /* Image Sensor Interface */ +#define AT91SAM9G45_ID_UDPHS 27 /* USB Device High Speed */ +#define AT91SAM9G45_ID_AESTDESSHA 28 /* AES + T-DES + SHA */ +#define AT91SAM9G45_ID_MCI1 29 /* High Speed Multimedia Card Interface 1 */ +#define AT91SAM9G45_ID_VDEC 30 /* Video Decoder */ +#define AT91SAM9G45_ID_IRQ0 31 /* Advanced Interrupt Controller */ + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9G45_BASE_UDPHS 0xfff78000 +#define AT91SAM9G45_BASE_TCB0 0xfff7c000 +#define AT91SAM9G45_BASE_TC0 0xfff7c000 +#define AT91SAM9G45_BASE_TC1 0xfff7c040 +#define AT91SAM9G45_BASE_TC2 0xfff7c080 +#define AT91SAM9G45_BASE_MCI0 0xfff80000 +#define AT91SAM9G45_BASE_TWI0 0xfff84000 +#define AT91SAM9G45_BASE_TWI1 0xfff88000 +#define AT91SAM9G45_BASE_US0 0xfff8c000 +#define AT91SAM9G45_BASE_US1 0xfff90000 +#define AT91SAM9G45_BASE_US2 0xfff94000 +#define AT91SAM9G45_BASE_US3 0xfff98000 +#define AT91SAM9G45_BASE_SSC0 0xfff9c000 +#define AT91SAM9G45_BASE_SSC1 0xfffa0000 +#define AT91SAM9G45_BASE_SPI0 0xfffa4000 +#define AT91SAM9G45_BASE_SPI1 0xfffa8000 +#define AT91SAM9G45_BASE_AC97C 0xfffac000 +#define AT91SAM9G45_BASE_TSC 0xfffb0000 +#define AT91SAM9G45_BASE_ISI 0xfffb4000 +#define AT91SAM9G45_BASE_PWMC 0xfffb8000 +#define AT91SAM9G45_BASE_EMAC 0xfffbc000 +#define AT91SAM9G45_BASE_AES 0xfffc0000 +#define AT91SAM9G45_BASE_TDES 0xfffc4000 +#define AT91SAM9G45_BASE_SHA 0xfffc8000 +#define AT91SAM9G45_BASE_TRNG 0xfffcc000 +#define AT91SAM9G45_BASE_MCI1 0xfffd0000 +#define AT91SAM9G45_BASE_TCB1 0xfffd4000 +#define AT91SAM9G45_BASE_TC3 0xfffd4000 +#define AT91SAM9G45_BASE_TC4 0xfffd4040 +#define AT91SAM9G45_BASE_TC5 0xfffd4080 +#define AT91_BASE_SYS 0xffffe200 + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_ECC (0xffffe200 - AT91_BASE_SYS) +#define AT91_DDRSDRC1 (0xffffe400 - AT91_BASE_SYS) +#define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS) +#define AT91_SMC (0xffffe800 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS) +#define AT91_DMA (0xffffec00 - AT91_BASE_SYS) +#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS) +#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS) +#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) +#define AT91_RTC (0xfffffdb0 - AT91_BASE_SYS) + +#define AT91_USART0 AT91SAM9G45_BASE_US0 +#define AT91_USART1 AT91SAM9G45_BASE_US1 +#define AT91_USART2 AT91SAM9G45_BASE_US2 +#define AT91_USART3 AT91SAM9G45_BASE_US3 + +/* + * Internal Memory. + */ +#define AT91SAM9G45_SRAM_BASE 0x00300000 /* Internal SRAM base address */ +#define AT91SAM9G45_SRAM_SIZE SZ_64K /* Internal SRAM size (64Kb) */ + +#define AT91SAM9G45_ROM_BASE 0x00400000 /* Internal ROM base address */ +#define AT91SAM9G45_ROM_SIZE SZ_64K /* Internal ROM size (64Kb) */ + +#define AT91SAM9G45_LCDC_BASE 0x00500000 /* LCD Controller */ +#define AT91SAM9G45_UDPHS_FIFO 0x00600000 /* USB Device HS controller */ +#define AT91SAM9G45_OHCI_BASE 0x00700000 /* USB Host controller (OHCI) */ +#define AT91SAM9G45_EHCI_BASE 0x00800000 /* USB Host controller (EHCI) */ +#define AT91SAM9G45_VDEC_BASE 0x00900000 /* Video Decoder Controller */ + +#define CONFIG_DRAM_BASE AT91_CHIPSELECT_6 + +#define CONSISTENT_DMA_SIZE SZ_4M + +#endif diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h new file mode 100644 index 0000000000000..c972d60e0aebb --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h @@ -0,0 +1,153 @@ +/* + * Matrix-centric header file for the AT91SAM9G45 family + * + * Copyright (C) 2008-2009 Atmel Corporation. + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9G45 preliminary datasheet. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91SAM9G45_MATRIX_H +#define AT91SAM9G45_MATRIX_H + +#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ +#define AT91_MATRIX_MCFG6 (AT91_MATRIX + 0x18) /* Master Configuration Register 6 */ +#define AT91_MATRIX_MCFG7 (AT91_MATRIX + 0x1C) /* Master Configuration Register 7 */ +#define AT91_MATRIX_MCFG8 (AT91_MATRIX + 0x20) /* Master Configuration Register 8 */ +#define AT91_MATRIX_MCFG9 (AT91_MATRIX + 0x24) /* Master Configuration Register 9 */ +#define AT91_MATRIX_MCFG10 (AT91_MATRIX + 0x28) /* Master Configuration Register 10 */ +#define AT91_MATRIX_MCFG11 (AT91_MATRIX + 0x2C) /* Master Configuration Register 11 */ +#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) +#define AT91_MATRIX_ULBT_THIRTYTWO (5 << 0) +#define AT91_MATRIX_ULBT_SIXTYFOUR (6 << 0) +#define AT91_MATRIX_ULBT_128 (7 << 0) + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SCFG5 (AT91_MATRIX + 0x54) /* Slave Configuration Register 5 */ +#define AT91_MATRIX_SCFG6 (AT91_MATRIX + 0x58) /* Slave Configuration Register 6 */ +#define AT91_MATRIX_SCFG7 (AT91_MATRIX + 0x5C) /* Slave Configuration Register 7 */ +#define AT91_MATRIX_SLOT_CYCLE (0x1ff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (0xf << 18) /* Fixed Index of Default Master */ + +#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRBS0 (AT91_MATRIX + 0x84) /* Priority Register B for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRBS1 (AT91_MATRIX + 0x8C) /* Priority Register B for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRBS2 (AT91_MATRIX + 0x94) /* Priority Register B for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRBS3 (AT91_MATRIX + 0x9C) /* Priority Register B for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ +#define AT91_MATRIX_PRBS4 (AT91_MATRIX + 0xA4) /* Priority Register B for Slave 4 */ +#define AT91_MATRIX_PRAS5 (AT91_MATRIX + 0xA8) /* Priority Register A for Slave 5 */ +#define AT91_MATRIX_PRBS5 (AT91_MATRIX + 0xAC) /* Priority Register B for Slave 5 */ +#define AT91_MATRIX_PRAS6 (AT91_MATRIX + 0xB0) /* Priority Register A for Slave 6 */ +#define AT91_MATRIX_PRBS6 (AT91_MATRIX + 0xB4) /* Priority Register B for Slave 6 */ +#define AT91_MATRIX_PRAS7 (AT91_MATRIX + 0xB8) /* Priority Register A for Slave 7 */ +#define AT91_MATRIX_PRBS7 (AT91_MATRIX + 0xBC) /* Priority Register B for Slave 7 */ +#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ +#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ +#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ +#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ +#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ +#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ +#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */ +#define AT91_MATRIX_M7PR (3 << 28) /* Master 7 Priority */ +#define AT91_MATRIX_M8PR (3 << 0) /* Master 8 Priority (in Register B) */ +#define AT91_MATRIX_M9PR (3 << 4) /* Master 9 Priority (in Register B) */ +#define AT91_MATRIX_M10PR (3 << 8) /* Master 10 Priority (in Register B) */ +#define AT91_MATRIX_M11PR (3 << 12) /* Master 11 Priority (in Register B) */ + +#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ +#define AT91_MATRIX_RCB2 (1 << 2) +#define AT91_MATRIX_RCB3 (1 << 3) +#define AT91_MATRIX_RCB4 (1 << 4) +#define AT91_MATRIX_RCB5 (1 << 5) +#define AT91_MATRIX_RCB6 (1 << 6) +#define AT91_MATRIX_RCB7 (1 << 7) +#define AT91_MATRIX_RCB8 (1 << 8) +#define AT91_MATRIX_RCB9 (1 << 9) +#define AT91_MATRIX_RCB10 (1 << 10) +#define AT91_MATRIX_RCB11 (1 << 11) + +#define AT91_MATRIX_TCMR (AT91_MATRIX + 0x110) /* TCM Configuration Register */ +#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */ +#define AT91_MATRIX_ITCM_0 (0 << 0) +#define AT91_MATRIX_ITCM_32 (6 << 0) +#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */ +#define AT91_MATRIX_DTCM_0 (0 << 4) +#define AT91_MATRIX_DTCM_32 (6 << 4) +#define AT91_MATRIX_DTCM_64 (7 << 4) +#define AT91_MATRIX_TCM_NWS (0x1 << 11) /* Wait state TCM register */ +#define AT91_MATRIX_TCM_NO_WS (0x0 << 11) +#define AT91_MATRIX_TCM_ONE_WS (0x1 << 11) + +#define AT91_MATRIX_VIDEO (AT91_MATRIX + 0x118) /* Video Mode Configuration Register */ +#define AT91C_VDEC_SEL (0x1 << 0) /* Video Mode Selection */ +#define AT91C_VDEC_SEL_OFF (0 << 0) +#define AT91C_VDEC_SEL_ON (1 << 0) + +#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x128) /* EBI Chip Select Assignment Register */ +#define AT91_MATRIX_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI_CS3A_SMC (0 << 3) +#define AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA (1 << 3) +#define AT91_MATRIX_EBI_CS4A (1 << 4) /* Chip Select 4 Assignment */ +#define AT91_MATRIX_EBI_CS4A_SMC (0 << 4) +#define AT91_MATRIX_EBI_CS4A_SMC_CF0 (1 << 4) +#define AT91_MATRIX_EBI_CS5A (1 << 5) /* Chip Select 5 Assignment */ +#define AT91_MATRIX_EBI_CS5A_SMC (0 << 5) +#define AT91_MATRIX_EBI_CS5A_SMC_CF1 (1 << 5) +#define AT91_MATRIX_EBI_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI_DBPU_ON (0 << 8) +#define AT91_MATRIX_EBI_DBPU_OFF (1 << 8) +#define AT91_MATRIX_EBI_VDDIOMSEL (1 << 16) /* Memory voltage selection */ +#define AT91_MATRIX_EBI_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_EBI_VDDIOMSEL_3_3V (1 << 16) +#define AT91_MATRIX_EBI_EBI_IOSR (1 << 17) /* EBI I/O slew rate selection */ +#define AT91_MATRIX_EBI_EBI_IOSR_REDUCED (0 << 17) +#define AT91_MATRIX_EBI_EBI_IOSR_NORMAL (1 << 17) +#define AT91_MATRIX_EBI_DDR_IOSR (1 << 18) /* DDR2 dedicated port I/O slew rate selection */ +#define AT91_MATRIX_EBI_DDR_IOSR_REDUCED (0 << 18) +#define AT91_MATRIX_EBI_DDR_IOSR_NORMAL (1 << 18) + +#define AT91_MATRIX_WPMR (AT91_MATRIX + 0x1E4) /* Write Protect Mode Register */ +#define AT91_MATRIX_WPMR_WPEN (1 << 0) /* Write Protect ENable */ +#define AT91_MATRIX_WPMR_WP_WPDIS (0 << 0) +#define AT91_MATRIX_WPMR_WP_WPEN (1 << 0) +#define AT91_MATRIX_WPMR_WPKEY (0xFFFFFF << 8) /* Write Protect KEY */ + +#define AT91_MATRIX_WPSR (AT91_MATRIX + 0x1E8) /* Write Protect Status Register */ +#define AT91_MATRIX_WPSR_WPVS (1 << 0) /* Write Protect Violation Status */ +#define AT91_MATRIX_WPSR_NO_WPV (0 << 0) +#define AT91_MATRIX_WPSR_WPV (1 << 0) +#define AT91_MATRIX_WPSR_WPVSRC (0xFFFF << 8) /* Write Protect Violation Source */ + +#endif diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index c554c3e4d5532..b73e7bf097daa 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -23,6 +23,7 @@ #define ARCH_ID_AT91SAM9263 0x019607a0 #define ARCH_ID_AT91SAM9G20 0x019905a0 #define ARCH_ID_AT91SAM9RL64 0x019b03a0 +#define ARCH_ID_AT91SAM9G45 0x819b05a0 #define ARCH_ID_AT91CAP9 0x039A03A0 #define ARCH_ID_AT91SAM9XE128 0x329973a0 @@ -39,6 +40,15 @@ static inline unsigned long at91_cpu_identify(void) return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION); } +#define ARCH_EXID_AT91SAM9M11 0x00000001 +#define ARCH_EXID_AT91SAM9M10 0x00000002 +#define ARCH_EXID_AT91SAM9G45 0x00000004 + +static inline unsigned long at91_exid_identify(void) +{ + return at91_sys_read(AT91_DBGU_EXID); +} + #define ARCH_FAMILY_AT91X92 0x09200000 #define ARCH_FAMILY_AT91SAM9 0x01900000 @@ -99,6 +109,12 @@ static inline unsigned long at91cap9_rev_identify(void) #define cpu_is_at91sam9rl() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9G45 +#define cpu_is_at91sam9g45() (at91_cpu_identify() == ARCH_ID_AT91SAM9G45) +#else +#define cpu_is_at91sam9g45() (0) +#endif + #ifdef CONFIG_ARCH_AT91CAP9 #define cpu_is_at91cap9() (at91_cpu_identify() == ARCH_ID_AT91CAP9) #define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B) diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index da0b681c652cf..f0869170fa00e 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h @@ -26,6 +26,8 @@ #include <mach/at91sam9263.h> #elif defined(CONFIG_ARCH_AT91SAM9RL) #include <mach/at91sam9rl.h> +#elif defined(CONFIG_ARCH_AT91SAM9G45) +#include <mach/at91sam9g45.h> #elif defined(CONFIG_ARCH_AT91CAP9) #include <mach/at91cap9.h> #elif defined(CONFIG_ARCH_AT91X40) diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h index d84c9948becf5..38f6c4250c761 100644 --- a/arch/arm/mach-at91/include/mach/timex.h +++ b/arch/arm/mach-at91/include/mach/timex.h @@ -62,6 +62,11 @@ #define AT91SAM9_MASTER_CLOCK 132096000 #define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) +#elif defined(CONFIG_ARCH_AT91SAM9G45) + +#define AT91SAM9_MASTER_CLOCK 133333333 +#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) + #elif defined(CONFIG_ARCH_AT91CAP9) #define AT91CAP9_MASTER_CLOCK 100000000 -- GitLab From 789b23bc40a67d9a19bedc2655c6bcab79bcabd8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:36:58 +0100 Subject: [PATCH 0297/1002] [ARM] 5572/1: at91: Support for at91sam9g45 series: core chip & board support Here are the at91 specific files dedicated to the at91sam9g45 series. They mimic the traditional at91 way of managing chips & boards. The first board that embeds at91sam9g45 chip is the AT91SAM9G45-EKES. In the future, the main board for this 9g45 series will be the AT91SAM9M10G45-EK (I choose this last name for the board file). Simple drivers are enabled in _devices and board- files. Newer peripheral support will be added in future patches. Incuded peripherals support (for now): - USART - SPI - Ethernet - NAND flash - LCD - gpio/joystick/buttons - leds and pwm Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/Kconfig | 26 +- arch/arm/mach-at91/Makefile | 4 + arch/arm/mach-at91/Makefile.boot | 4 + arch/arm/mach-at91/at91sam9g45.c | 360 +++++++ arch/arm/mach-at91/at91sam9g45_devices.c | 1230 ++++++++++++++++++++++ arch/arm/mach-at91/board-sam9m10g45ek.c | 389 +++++++ arch/arm/mach-at91/generic.h | 2 + arch/arm/mach-at91/include/mach/board.h | 8 +- drivers/net/Kconfig | 2 +- drivers/video/Kconfig | 2 +- 10 files changed, 2022 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-at91/at91sam9g45.c create mode 100644 arch/arm/mach-at91/at91sam9g45_devices.c create mode 100644 arch/arm/mach-at91/board-sam9m10g45ek.c diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 323b47f2b52f2..22309ba97fa60 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -41,6 +41,12 @@ config ARCH_AT91SAM9G20 select GENERIC_TIME select GENERIC_CLOCKEVENTS +config ARCH_AT91SAM9G45 + bool "AT91SAM9G45" + select CPU_ARM926T + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + config ARCH_AT91CAP9 bool "AT91CAP9" select CPU_ARM926T @@ -280,6 +286,22 @@ endif # ---------------------------------------------------------- +if ARCH_AT91SAM9G45 + +comment "AT91SAM9G45 Board Type" + +config MACH_AT91SAM9G45EKES + bool "Atmel AT91SAM9G45-EKES Evaluation Kit" + depends on ARCH_AT91SAM9G45 + help + Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit. + "ES" at the end of the name means that this board is an + Engineering Sample. + +endif + +# ---------------------------------------------------------- + if ARCH_AT91CAP9 comment "AT91CAP9 Board Type" @@ -321,7 +343,7 @@ config MTD_AT91_DATAFLASH_CARD config MTD_NAND_ATMEL_BUSWIDTH_16 bool "Enable 16-bit data bus interface to NAND flash" - depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_AT91CAP9ADK) + depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_AT91SAM9G45EKES || MACH_AT91CAP9ADK) help On AT91SAM926x boards both types of NAND flash can be present (8 and 16 bit data bus width). @@ -383,7 +405,7 @@ config AT91_EARLY_USART2 config AT91_EARLY_USART3 bool "USART3" - depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260 || ARCH_AT91SAM9G20) + depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45) config AT91_EARLY_USART4 bool "USART4" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index c69ff237fd148..2975f9ab861c8 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_d obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o + obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o @@ -55,6 +56,9 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o # AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o +# AT91SAM9G45 board-specific support +obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o + # AT91CAP9 board-specific support obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index 071a2506a69fb..3462b815054ac 100644 --- a/arch/arm/mach-at91/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot @@ -7,6 +7,10 @@ ifeq ($(CONFIG_ARCH_AT91CAP9),y) zreladdr-y := 0x70008000 params_phys-y := 0x70000100 initrd_phys-y := 0x70410000 +else ifeq ($(CONFIG_ARCH_AT91SAM9G45),y) + zreladdr-y := 0x70008000 +params_phys-y := 0x70000100 +initrd_phys-y := 0x70410000 else zreladdr-y := 0x20008000 params_phys-y := 0x20000100 diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c new file mode 100644 index 0000000000000..85166b7e69a18 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -0,0 +1,360 @@ +/* + * Chip-specific setup code for the AT91SAM9G45 family + * + * Copyright (C) 2009 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/pm.h> + +#include <asm/irq.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <mach/at91sam9g45.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> +#include <mach/at91_shdwc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9g45_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9G45_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91SAM9G45_SRAM_BASE), + .length = AT91SAM9G45_SRAM_SIZE, + .type = MT_DEVICE, + } +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioDE_clk = { + .name = "pioDE_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_PIODE, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { + .name = "usart3_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_US3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc0_clk = { + .name = "mci0_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_MCI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi0_clk = { + .name = "twi0_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_TWI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi1_clk = { + .name = "twi1_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_TWI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc0_clk = { + .name = "ssc0_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_SSC0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc1_clk = { + .name = "ssc1_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_SSC1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tcb_clk = { + .name = "tcb_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_TCB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pwm_clk = { + .name = "pwm_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_PWMC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tsc_clk = { + .name = "tsc_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_TSC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk dma_clk = { + .name = "dma_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_DMA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk uhphs_clk = { + .name = "uhphs_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_UHPHS, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ac97_clk = { + .name = "ac97_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_AC97C, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk macb_clk = { + .name = "macb_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udphs_clk = { + .name = "udphs_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_UDPHS, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc1_clk = { + .name = "mci1_clk", + .pmc_mask = 1 << AT91SAM9G45_ID_MCI1, + .type = CLK_TYPE_PERIPHERAL, +}; + +/* One additional fake clock for ohci */ +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 0, + .type = CLK_TYPE_PERIPHERAL, + .parent = &uhphs_clk, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &pioDE_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &usart3_clk, + &mmc0_clk, + &twi0_clk, + &twi1_clk, + &spi0_clk, + &spi1_clk, + &ssc0_clk, + &ssc1_clk, + &tcb_clk, + &pwm_clk, + &tsc_clk, + &dma_clk, + &uhphs_clk, + &lcdc_clk, + &ac97_clk, + &macb_clk, + &isi_clk, + &udphs_clk, + &mmc1_clk, + // irq0 + &ohci_clk, +}; + +/* + * The two programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; + +static void __init at91sam9g45_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9g45_gpio[] = { + { + .id = AT91SAM9G45_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9G45_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9G45_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + }, { + .id = AT91SAM9G45_ID_PIODE, + .offset = AT91_PIOD, + .clock = &pioDE_clk, + }, { + .id = AT91SAM9G45_ID_PIODE, + .offset = AT91_PIOE, + .clock = &pioDE_clk, + } +}; + +static void at91sam9g45_reset(void) +{ + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + +static void at91sam9g45_poweroff(void) +{ + at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW); +} + + +/* -------------------------------------------------------------------- + * AT91SAM9G45 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9g45_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc)); + + at91_arch_reset = at91sam9g45_reset; + pm_power_off = at91sam9g45_poweroff; + at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9g45_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9g45_gpio, 5); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller (FIQ) */ + 7, /* System Peripherals */ + 1, /* Parallel IO Controller A */ + 1, /* Parallel IO Controller B */ + 1, /* Parallel IO Controller C */ + 1, /* Parallel IO Controller D and E */ + 0, + 5, /* USART 0 */ + 5, /* USART 1 */ + 5, /* USART 2 */ + 5, /* USART 3 */ + 0, /* Multimedia Card Interface 0 */ + 6, /* Two-Wire Interface 0 */ + 6, /* Two-Wire Interface 1 */ + 5, /* Serial Peripheral Interface 0 */ + 5, /* Serial Peripheral Interface 1 */ + 4, /* Serial Synchronous Controller 0 */ + 4, /* Serial Synchronous Controller 1 */ + 0, /* Timer Counter 0, 1, 2, 3, 4 and 5 */ + 0, /* Pulse Width Modulation Controller */ + 0, /* Touch Screen Controller */ + 0, /* DMA Controller */ + 2, /* USB Host High Speed port */ + 3, /* LDC Controller */ + 5, /* AC97 Controller */ + 3, /* Ethernet */ + 0, /* Image Sensor Interface */ + 2, /* USB Device High speed port */ + 0, + 0, /* Multimedia Card Interface 1 */ + 0, + 0, /* Advanced Interrupt Controller (IRQ0) */ +}; + +void __init at91sam9g45_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9g45_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c new file mode 100644 index 0000000000000..d746e8621bc2c --- /dev/null +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -0,0 +1,1230 @@ +/* + * On-Chip devices setup code for the AT91SAM9G45 family + * + * Copyright (C) 2009 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/i2c-gpio.h> + +#include <linux/fb.h> +#include <video/atmel_lcdc.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9g45.h> +#include <mach/at91sam9g45_matrix.h> +#include <mach/at91sam9_smc.h> + +#include "generic.h" + + +/* -------------------------------------------------------------------- + * USB Host (OHCI) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = DMA_BIT_MASK(32); +static struct at91_usbh_data usbh_ohci_data; + +static struct resource usbh_ohci_resources[] = { + [0] = { + .start = AT91SAM9G45_OHCI_BASE, + .end = AT91SAM9G45_OHCI_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_UHPHS, + .end = AT91SAM9G45_ID_UHPHS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_ohci_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &usbh_ohci_data, + }, + .resource = usbh_ohci_resources, + .num_resources = ARRAY_SIZE(usbh_ohci_resources), +}; + +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + usbh_ohci_data = *data; + platform_device_register(&at91_usbh_ohci_device); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB HS Device (Gadget) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE) +static struct resource usba_udc_resources[] = { + [0] = { + .start = AT91SAM9G45_UDPHS_FIFO, + .end = AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_BASE_UDPHS, + .end = AT91SAM9G45_BASE_UDPHS + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = AT91SAM9G45_ID_UDPHS, + .end = AT91SAM9G45_ID_UDPHS, + .flags = IORESOURCE_IRQ, + }, +}; + +#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ + [idx] = { \ + .name = nam, \ + .index = idx, \ + .fifo_size = maxpkt, \ + .nr_banks = maxbk, \ + .can_dma = dma, \ + .can_isoc = isoc, \ + } + +static struct usba_ep_data usba_udc_ep[] __initdata = { + EP("ep0", 0, 64, 1, 0, 0), + EP("ep1", 1, 1024, 2, 1, 1), + EP("ep2", 2, 1024, 2, 1, 1), + EP("ep3", 3, 1024, 3, 1, 0), + EP("ep4", 4, 1024, 3, 1, 0), + EP("ep5", 5, 1024, 3, 1, 1), + EP("ep6", 6, 1024, 3, 1, 1), +}; + +#undef EP + +/* + * pdata doesn't have room for any endpoints, so we need to + * append room for the ones we need right after it. + */ +static struct { + struct usba_platform_data pdata; + struct usba_ep_data ep[7]; +} usba_udc_data; + +static struct platform_device at91_usba_udc_device = { + .name = "atmel_usba_udc", + .id = -1, + .dev = { + .platform_data = &usba_udc_data.pdata, + }, + .resource = usba_udc_resources, + .num_resources = ARRAY_SIZE(usba_udc_resources), +}; + +void __init at91_add_device_usba(struct usba_platform_data *data) +{ + usba_udc_data.pdata.vbus_pin = -EINVAL; + usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep); + memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));; + + if (data && data->vbus_pin > 0) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + usba_udc_data.pdata.vbus_pin = data->vbus_pin; + } + + /* Pullup pin is handled internally by USB device peripheral */ + + /* Clocks */ + at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk"); + at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk"); + + platform_device_register(&at91_usba_udc_device); +} +#else +void __init at91_add_device_usba(struct usba_platform_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = DMA_BIT_MASK(32); +static struct at91_eth_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_EMAC, + .end = AT91SAM9G45_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_EMAC, + .end = AT91SAM9G45_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA11, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PA29, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PA30, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PA8, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PA9, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PA28, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PA6, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA7, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PA27, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9g45_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE) +static struct atmel_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + [0] = { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC, + .end = AT91_BASE_SYS + AT91_ECC + SZ_512 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9g45_nand_device = { + .name = "atmel_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct atmel_nand_data *data) +{ + unsigned long csa; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + nand_data = *data; + platform_device_register(&at91sam9g45_nand_device); +} +#else +void __init at91_add_device_nand(struct atmel_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) +static struct i2c_gpio_platform_data pdata_i2c0 = { + .sda_pin = AT91_PIN_PA20, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA21, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9g45_twi0_device = { + .name = "i2c-gpio", + .id = 0, + .dev.platform_data = &pdata_i2c0, +}; + +static struct i2c_gpio_platform_data pdata_i2c1 = { + .sda_pin = AT91_PIN_PB10, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PB11, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9g45_twi1_device = { + .name = "i2c-gpio", + .id = 1, + .dev.platform_data = &pdata_i2c1, +}; + +void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) +{ + i2c_register_board_info(i2c_id, devices, nr_devices); + + if (i2c_id == 0) { + at91_set_GPIO_periph(AT91_PIN_PA20, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA20, 1); + + at91_set_GPIO_periph(AT91_PIN_PA21, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA21, 1); + + platform_device_register(&at91sam9g45_twi0_device); + } else { + at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PB10, 1); + + at91_set_GPIO_periph(AT91_PIN_PB11, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PB11, 1); + + platform_device_register(&at91sam9g45_twi1_device); + } +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +static struct resource twi0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TWI0, + .end = AT91SAM9G45_BASE_TWI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_TWI0, + .end = AT91SAM9G45_ID_TWI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_twi0_device = { + .name = "at91_i2c", + .id = 0, + .resource = twi0_resources, + .num_resources = ARRAY_SIZE(twi0_resources), +}; + +static struct resource twi1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TWI1, + .end = AT91SAM9G45_BASE_TWI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_TWI1, + .end = AT91SAM9G45_ID_TWI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_twi1_device = { + .name = "at91_i2c", + .id = 1, + .resource = twi1_resources, + .num_resources = ARRAY_SIZE(twi1_resources), +}; + +void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) +{ + i2c_register_board_info(i2c_id, devices, nr_devices); + + /* pins used for TWI interface */ + if (i2c_id == 0) { + at91_set_A_periph(AT91_PIN_PA20, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA20, 1); + + at91_set_A_periph(AT91_PIN_PA21, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA21, 1); + + platform_device_register(&at91sam9g45_twi0_device); + } else { + at91_set_A_periph(AT91_PIN_PB10, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PB10, 1); + + at91_set_A_periph(AT91_PIN_PB11, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PB11, 1); + + platform_device_register(&at91sam9g45_twi1_device); + } +} +#else +void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = DMA_BIT_MASK(32); + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_SPI0, + .end = AT91SAM9G45_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_SPI0, + .end = AT91SAM9G45_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_SPI1, + .end = AT91SAM9G45_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_SPI1, + .end = AT91SAM9G45_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI0_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9g45_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9g45_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB15, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB16, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9g45_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9g45_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LCD Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) +static u64 lcdc_dmamask = DMA_BIT_MASK(32); +static struct atmel_lcdfb_info lcdc_data; + +static struct resource lcdc_resources[] = { + [0] = { + .start = AT91SAM9G45_LCDC_BASE, + .end = AT91SAM9G45_LCDC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_LCDC, + .end = AT91SAM9G45_ID_LCDC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_lcdc_device = { + .name = "atmel_lcdfb", + .id = 0, + .dev = { + .dma_mask = &lcdc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &lcdc_data, + }, + .resource = lcdc_resources, + .num_resources = ARRAY_SIZE(lcdc_resources), +}; + +void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) +{ + if (!data) + return; + + at91_set_A_periph(AT91_PIN_PE0, 0); /* LCDDPWR */ + + at91_set_A_periph(AT91_PIN_PE2, 0); /* LCDCC */ + at91_set_A_periph(AT91_PIN_PE3, 0); /* LCDVSYNC */ + at91_set_A_periph(AT91_PIN_PE4, 0); /* LCDHSYNC */ + at91_set_A_periph(AT91_PIN_PE5, 0); /* LCDDOTCK */ + at91_set_A_periph(AT91_PIN_PE6, 0); /* LCDDEN */ + at91_set_A_periph(AT91_PIN_PE7, 0); /* LCDD0 */ + at91_set_A_periph(AT91_PIN_PE8, 0); /* LCDD1 */ + at91_set_A_periph(AT91_PIN_PE9, 0); /* LCDD2 */ + at91_set_A_periph(AT91_PIN_PE10, 0); /* LCDD3 */ + at91_set_A_periph(AT91_PIN_PE11, 0); /* LCDD4 */ + at91_set_A_periph(AT91_PIN_PE12, 0); /* LCDD5 */ + at91_set_A_periph(AT91_PIN_PE13, 0); /* LCDD6 */ + at91_set_A_periph(AT91_PIN_PE14, 0); /* LCDD7 */ + at91_set_A_periph(AT91_PIN_PE15, 0); /* LCDD8 */ + at91_set_A_periph(AT91_PIN_PE16, 0); /* LCDD9 */ + at91_set_A_periph(AT91_PIN_PE17, 0); /* LCDD10 */ + at91_set_A_periph(AT91_PIN_PE18, 0); /* LCDD11 */ + at91_set_A_periph(AT91_PIN_PE19, 0); /* LCDD12 */ + at91_set_A_periph(AT91_PIN_PE20, 0); /* LCDD13 */ + at91_set_A_periph(AT91_PIN_PE21, 0); /* LCDD14 */ + at91_set_A_periph(AT91_PIN_PE22, 0); /* LCDD15 */ + at91_set_A_periph(AT91_PIN_PE23, 0); /* LCDD16 */ + at91_set_A_periph(AT91_PIN_PE24, 0); /* LCDD17 */ + at91_set_A_periph(AT91_PIN_PE25, 0); /* LCDD18 */ + at91_set_A_periph(AT91_PIN_PE26, 0); /* LCDD19 */ + at91_set_A_periph(AT91_PIN_PE27, 0); /* LCDD20 */ + at91_set_A_periph(AT91_PIN_PE28, 0); /* LCDD21 */ + at91_set_A_periph(AT91_PIN_PE29, 0); /* LCDD22 */ + at91_set_A_periph(AT91_PIN_PE30, 0); /* LCDD23 */ + + lcdc_data = *data; + platform_device_register(&at91_lcdc_device); +} +#else +void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Timer/Counter block + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_ATMEL_TCLIB +static struct resource tcb0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TCB0, + .end = AT91SAM9G45_BASE_TCB0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_TCB, + .end = AT91SAM9G45_ID_TCB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_tcb0_device = { + .name = "atmel_tcb", + .id = 0, + .resource = tcb0_resources, + .num_resources = ARRAY_SIZE(tcb0_resources), +}; + +/* TCB1 begins with TC3 */ +static struct resource tcb1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_TCB1, + .end = AT91SAM9G45_BASE_TCB1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_TCB, + .end = AT91SAM9G45_ID_TCB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_tcb1_device = { + .name = "atmel_tcb", + .id = 1, + .resource = tcb1_resources, + .num_resources = ARRAY_SIZE(tcb1_resources), +}; + +static void __init at91_add_device_tc(void) +{ + /* this chip has one clock and irq for all six TC channels */ + at91_clock_associate("tcb_clk", &at91sam9g45_tcb0_device.dev, "t0_clk"); + platform_device_register(&at91sam9g45_tcb0_device); + at91_clock_associate("tcb_clk", &at91sam9g45_tcb1_device.dev, "t0_clk"); + platform_device_register(&at91sam9g45_tcb1_device); +} +#else +static void __init at91_add_device_tc(void) { } +#endif + + +/* -------------------------------------------------------------------- + * RTC + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE) +static struct platform_device at91sam9g45_rtc_device = { + .name = "at91_rtc", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_rtc(void) +{ + platform_device_register(&at91sam9g45_rtc_device); +} +#else +static void __init at91_add_device_rtc(void) {} +#endif + + +/* -------------------------------------------------------------------- + * RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { + { + .start = AT91_BASE_SYS + AT91_RTT, + .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9g45_rtt_device = { + .name = "at91_rtt", + .id = 0, + .resource = rtt_resources, + .num_resources = ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ + platform_device_register(&at91sam9g45_rtt_device); +} + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE) +static struct platform_device at91sam9g45_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91sam9g45_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + +/* -------------------------------------------------------------------- + * PWM + * --------------------------------------------------------------------*/ + +#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE) +static u32 pwm_mask; + +static struct resource pwm_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_PWMC, + .end = AT91SAM9G45_BASE_PWMC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_PWMC, + .end = AT91SAM9G45_ID_PWMC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_pwm0_device = { + .name = "atmel_pwm", + .id = -1, + .dev = { + .platform_data = &pwm_mask, + }, + .resource = pwm_resources, + .num_resources = ARRAY_SIZE(pwm_resources), +}; + +void __init at91_add_device_pwm(u32 mask) +{ + if (mask & (1 << AT91_PWM0)) + at91_set_B_periph(AT91_PIN_PD24, 1); /* enable PWM0 */ + + if (mask & (1 << AT91_PWM1)) + at91_set_B_periph(AT91_PIN_PD31, 1); /* enable PWM1 */ + + if (mask & (1 << AT91_PWM2)) + at91_set_B_periph(AT91_PIN_PD26, 1); /* enable PWM2 */ + + if (mask & (1 << AT91_PWM3)) + at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */ + + pwm_mask = mask; + + platform_device_register(&at91sam9g45_pwm0_device); +} +#else +void __init at91_add_device_pwm(u32 mask) {} +#endif + + +/* -------------------------------------------------------------------- + * SSC -- Synchronous Serial Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE) +static u64 ssc0_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_SSC0, + .end = AT91SAM9G45_BASE_SSC0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_SSC0, + .end = AT91SAM9G45_ID_SSC0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_ssc0_device = { + .name = "ssc", + .id = 0, + .dev = { + .dma_mask = &ssc0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc0_resources, + .num_resources = ARRAY_SIZE(ssc0_resources), +}; + +static inline void configure_ssc0_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PD1, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PD0, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PD2, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PD3, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PD4, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PD5, 1); +} + +static u64 ssc1_dmamask = DMA_BIT_MASK(32); + +static struct resource ssc1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_SSC1, + .end = AT91SAM9G45_BASE_SSC1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_SSC1, + .end = AT91SAM9G45_ID_SSC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9g45_ssc1_device = { + .name = "ssc", + .id = 1, + .dev = { + .dma_mask = &ssc1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ssc1_resources, + .num_resources = ARRAY_SIZE(ssc1_resources), +}; + +static inline void configure_ssc1_pins(unsigned pins) +{ + if (pins & ATMEL_SSC_TF) + at91_set_A_periph(AT91_PIN_PD14, 1); + if (pins & ATMEL_SSC_TK) + at91_set_A_periph(AT91_PIN_PD12, 1); + if (pins & ATMEL_SSC_TD) + at91_set_A_periph(AT91_PIN_PD10, 1); + if (pins & ATMEL_SSC_RD) + at91_set_A_periph(AT91_PIN_PD11, 1); + if (pins & ATMEL_SSC_RK) + at91_set_A_periph(AT91_PIN_PD13, 1); + if (pins & ATMEL_SSC_RF) + at91_set_A_periph(AT91_PIN_PD15, 1); +} + +/* + * SSC controllers are accessed through library code, instead of any + * kind of all-singing/all-dancing driver. For example one could be + * used by a particular I2S audio codec's driver, while another one + * on the same system might be used by a custom data capture driver. + */ +void __init at91_add_device_ssc(unsigned id, unsigned pins) +{ + struct platform_device *pdev; + + /* + * NOTE: caller is responsible for passing information matching + * "pins" to whatever will be using each particular controller. + */ + switch (id) { + case AT91SAM9G45_ID_SSC0: + pdev = &at91sam9g45_ssc0_device; + configure_ssc0_pins(pins); + at91_clock_associate("ssc0_clk", &pdev->dev, "pclk"); + break; + case AT91SAM9G45_ID_SSC1: + pdev = &at91sam9g45_ssc1_device; + configure_ssc1_pins(pins); + at91_clock_associate("ssc1_clk", &pdev->dev, "pclk"); + break; + default: + return; + } + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_ssc(unsigned id, unsigned pins) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static u64 dbgu_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at91sam9g45_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .dma_mask = &dbgu_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &dbgu_data, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB12, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PB13, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_US0, + .end = AT91SAM9G45_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_US0, + .end = AT91SAM9G45_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart0_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at91sam9g45_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .dma_mask = &uart0_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart0_data, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PB19, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PB18, 0); /* RXD0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PB17, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PB15, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_US1, + .end = AT91SAM9G45_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_US1, + .end = AT91SAM9G45_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart1_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at91sam9g45_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .dma_mask = &uart1_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart1_data, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PD16, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PD17, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_US2, + .end = AT91SAM9G45_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_US2, + .end = AT91SAM9G45_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart2_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at91sam9g45_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .dma_mask = &uart2_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart2_data, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PC9, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PC11, 0); /* CTS2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91SAM9G45_BASE_US3, + .end = AT91SAM9G45_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9G45_ID_US3, + .end = AT91SAM9G45_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static u64 uart3_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at91sam9g45_uart3_device = { + .name = "atmel_usart", + .id = 4, + .dev = { + .dma_mask = &uart3_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &uart3_data, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD3 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD3 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PA23, 0); /* RTS3 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PA24, 0); /* CTS3 */ +} + +static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ + struct platform_device *pdev; + + switch (id) { + case 0: /* DBGU */ + pdev = &at91sam9g45_dbgu_device; + configure_dbgu_pins(); + at91_clock_associate("mck", &pdev->dev, "usart"); + break; + case AT91SAM9G45_ID_US0: + pdev = &at91sam9g45_uart0_device; + configure_usart0_pins(pins); + at91_clock_associate("usart0_clk", &pdev->dev, "usart"); + break; + case AT91SAM9G45_ID_US1: + pdev = &at91sam9g45_uart1_device; + configure_usart1_pins(pins); + at91_clock_associate("usart1_clk", &pdev->dev, "usart"); + break; + case AT91SAM9G45_ID_US2: + pdev = &at91sam9g45_uart2_device; + configure_usart2_pins(pins); + at91_clock_associate("usart2_clk", &pdev->dev, "usart"); + break; + case AT91SAM9G45_ID_US3: + pdev = &at91sam9g45_uart3_device; + configure_usart3_pins(pins); + at91_clock_associate("usart3_clk", &pdev->dev, "usart"); + break; + default: + return; + } + pdev->id = portnr; /* update to mapped ID */ + + if (portnr < ATMEL_MAX_UART) + at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ + if (portnr < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[portnr]; +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } + + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} +#else +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + at91_add_device_rtc(); + at91_add_device_rtt(); + at91_add_device_watchdog(); + at91_add_device_tc(); + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c new file mode 100644 index 0000000000000..b8558eae52299 --- /dev/null +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -0,0 +1,389 @@ +/* + * Board-specific setup code for the AT91SAM9M10G45 Evaluation Kit family + * + * Covers: * AT91SAM9G45-EKES board + * * AT91SAM9M10G45-EK board + * + * Copyright (C) 2009 Atmel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/fb.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/leds.h> +#include <linux/clk.h> + +#include <mach/hardware.h> +#include <video/atmel_lcdc.h> + +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include <mach/at91_shdwc.h> + +#include "sam9_smc.h" +#include "generic.h" + + +static void __init ek_map_io(void) +{ + /* Initialize processor: 12.000 MHz crystal */ + at91sam9g45_initialize(12000000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 not connected on the -EK board */ + /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init ek_init_irq(void) +{ + at91sam9g45_init_interrupts(NULL); +} + + +/* + * USB HS Host port (common to OHCI & EHCI) + */ +static struct at91_usbh_data __initdata ek_usbh_hs_data = { + .ports = 2, + .vbus_pin = {AT91_PIN_PD1, AT91_PIN_PD3}, +}; + + +/* + * USB HS Device port + */ +static struct usba_platform_data __initdata ek_usba_udc_data = { + .vbus_pin = AT91_PIN_PB19, +}; + + +/* + * SPI devices. + */ +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +}; + + +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata ek_macb_data = { + .phy_irq_pin = AT91_PIN_PD5, + .is_rmii = 1, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = SZ_64M, + }, + { + .name = "Partition 2", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +/* det_pin is not connected */ +static struct atmel_nand_data __initdata ek_nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PC8, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + +static struct sam9_smc_config __initdata ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 3, +}; + +static void __init ek_add_device_nand(void) +{ + /* setup bus-width (8 or 16) */ + if (ek_nand_data.bus_width_16) + ek_nand_smc_config.mode |= AT91_SMC_DBW_16; + else + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&ek_nand_data); +} + + +/* + * LCD Controller + */ +#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE) +static struct fb_videomode at91_tft_vga_modes[] = { + { + .name = "LG", + .refresh = 60, + .xres = 480, .yres = 272, + .pixclock = KHZ2PICOS(9000), + + .left_margin = 1, .right_margin = 1, + .upper_margin = 40, .lower_margin = 1, + .hsync_len = 45, .vsync_len = 1, + + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, +}; + +static struct fb_monspecs at91fb_default_monspecs = { + .manufacturer = "LG", + .monitor = "LB043WQ1", + + .modedb = at91_tft_vga_modes, + .modedb_len = ARRAY_SIZE(at91_tft_vga_modes), + .hfmin = 15000, + .hfmax = 17640, + .vfmin = 57, + .vfmax = 67, +}; + +#define AT91SAM9G45_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \ + | ATMEL_LCDC_DISTYPE_TFT \ + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE) + +/* Driver datas */ +static struct atmel_lcdfb_info __initdata ek_lcdc_data = { + .lcdcon_is_backlight = true, + .default_bpp = 32, + .default_dmacon = ATMEL_LCDC_DMAEN, + .default_lcdcon2 = AT91SAM9G45_DEFAULT_LCDCON2, + .default_monspecs = &at91fb_default_monspecs, + .guard_time = 9, + .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, +}; + +#else +static struct atmel_lcdfb_info __initdata ek_lcdc_data; +#endif + + +/* + * GPIO Buttons + */ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button ek_buttons[] = { + { /* BP1, "leftclic" */ + .code = BTN_LEFT, + .gpio = AT91_PIN_PB6, + .active_low = 1, + .desc = "left_click", + .wakeup = 1, + }, + { /* BP2, "rightclic" */ + .code = BTN_RIGHT, + .gpio = AT91_PIN_PB7, + .active_low = 1, + .desc = "right_click", + .wakeup = 1, + }, + /* BP3, "joystick" */ + { + .code = KEY_LEFT, + .gpio = AT91_PIN_PB14, + .active_low = 1, + .desc = "Joystick Left", + }, + { + .code = KEY_RIGHT, + .gpio = AT91_PIN_PB15, + .active_low = 1, + .desc = "Joystick Right", + }, + { + .code = KEY_UP, + .gpio = AT91_PIN_PB16, + .active_low = 1, + .desc = "Joystick Up", + }, + { + .code = KEY_DOWN, + .gpio = AT91_PIN_PB17, + .active_low = 1, + .desc = "Joystick Down", + }, + { + .code = KEY_ENTER, + .gpio = AT91_PIN_PB18, + .active_low = 1, + .desc = "Joystick Press", + }, +}; + +static struct gpio_keys_platform_data ek_button_data = { + .buttons = ek_buttons, + .nbuttons = ARRAY_SIZE(ek_buttons), +}; + +static struct platform_device ek_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &ek_button_data, + } +}; + +static void __init ek_add_device_buttons(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ek_buttons); i++) { + at91_set_GPIO_periph(ek_buttons[i].gpio, 1); + at91_set_deglitch(ek_buttons[i].gpio, 1); + } + + platform_device_register(&ek_button_device); +} +#else +static void __init ek_add_device_buttons(void) {} +#endif + + +/* + * LEDs ... these could all be PWM-driven, for variable brightness + */ +static struct gpio_led ek_leds[] = { + { /* "top" led, red, powerled */ + .name = "d8", + .gpio = AT91_PIN_PD30, + .default_trigger = "heartbeat", + }, + { /* "left" led, green, userled2, pwm3 */ + .name = "d6", + .gpio = AT91_PIN_PD0, + .active_low = 1, + .default_trigger = "nand-disk", + }, +#if !(defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE)) + { /* "right" led, green, userled1, pwm1 */ + .name = "d7", + .gpio = AT91_PIN_PD31, + .active_low = 1, + .default_trigger = "mmc0", + }, +#endif +}; + + +/* + * PWM Leds + */ +static struct gpio_led ek_pwm_led[] = { +#if defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE) + { /* "right" led, green, userled1, pwm1 */ + .name = "d7", + .gpio = 1, /* is PWM channel number */ + .active_low = 1, + .default_trigger = "none", + }, +#endif +}; + + + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB HS Host */ + at91_add_device_usbh_ohci(&ek_usbh_hs_data); + /* USB HS Device */ + at91_add_device_usba(&ek_usba_udc_data); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); + /* Ethernet */ + at91_add_device_eth(&ek_macb_data); + /* NAND */ + ek_add_device_nand(); + /* I2C */ + at91_add_device_i2c(0, NULL, 0); + /* LCD Controller */ + at91_add_device_lcdc(&ek_lcdc_data); + /* Push Buttons */ + ek_add_device_buttons(); + /* LEDs */ + at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); + at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); +} + +MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index b5daf7f5e011a..88e413b384802 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -14,6 +14,7 @@ extern void __init at91sam9260_initialize(unsigned long main_clock); extern void __init at91sam9261_initialize(unsigned long main_clock); extern void __init at91sam9263_initialize(unsigned long main_clock); extern void __init at91sam9rl_initialize(unsigned long main_clock); +extern void __init at91sam9g45_initialize(unsigned long main_clock); extern void __init at91x40_initialize(unsigned long main_clock); extern void __init at91cap9_initialize(unsigned long main_clock); @@ -23,6 +24,7 @@ extern void __init at91sam9260_init_interrupts(unsigned int priority[]); extern void __init at91sam9261_init_interrupts(unsigned int priority[]); extern void __init at91sam9263_init_interrupts(unsigned int priority[]); extern void __init at91sam9rl_init_interrupts(unsigned int priority[]); +extern void __init at91sam9g45_init_interrupts(unsigned int priority[]); extern void __init at91x40_init_interrupts(unsigned int priority[]); extern void __init at91cap9_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index e6afff849b85e..74801d275cdc5 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -80,7 +80,8 @@ struct at91_eth_data { }; extern void __init at91_add_device_eth(struct at91_eth_data *data); -#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) +#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \ + || defined(CONFIG_ARCH_AT91SAM9G45) #define eth_platform_data at91_eth_data #endif @@ -90,6 +91,7 @@ struct at91_usbh_data { u8 vbus_pin[2]; /* port power-control pin */ }; extern void __init at91_add_device_usbh(struct at91_usbh_data *data); +extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); /* NAND / SmartMedia */ struct atmel_nand_data { @@ -105,7 +107,11 @@ struct atmel_nand_data { extern void __init at91_add_device_nand(struct atmel_nand_data *data); /* I2C*/ +#if defined(CONFIG_ARCH_AT91SAM9G45) +extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices); +#else extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices); +#endif /* SPI */ extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c155bd3ec9f1a..f053ba5c37ba0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -209,7 +209,7 @@ config MII config MACB tristate "Atmel MACB support" - depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91CAP9 + depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 select PHYLIB help The Atmel MACB ethernet interface is found on many AT32 and AT91 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d6d65ef85f541..36281823fe542 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -933,7 +933,7 @@ config FB_S1D13XXX config FB_ATMEL tristate "AT91/AT32 LCD Controller support" - depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || AVR32) + depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT -- GitLab From 6e750a8fc009fd0ae98704525d1d8e80d60e8cc9 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Sat, 27 Jun 2009 03:02:07 +0530 Subject: [PATCH 0298/1002] perf stat: Improve output Increase size for event name to handle bigger names like 'L1-d$-prefetch-misses' Changed scaled counters from percentage to a multiplicative factor because the latter is more expressive. Also aligned the scaling factor, otherwise sometimes it looks like: 384 iTLB-load-misses (4.74x scaled) 452029 branch-loads (8.00x scaled) 5892 branch-load-misses (20.39x scaled) 972315 iTLB-loads (3.24x scaled) Before: 150708 L1-d$-stores (scaled from 23.57%) 428804 L1-d$-prefetches (scaled from 23.47%) 314446 L1-d$-prefetch-misses (scaled from 23.42%) 252626137 L1-i$-loads (scaled from 23.24%) 5297550 dTLB-load-misses (scaled from 23.96%) 106992392 branch-loads (scaled from 23.67%) 5239561 branch-load-misses (scaled from 23.43%) After: 1731713 L1-d$-loads ( 14.25x scaled) 44241 L1-d$-prefetches ( 3.88x scaled) 21076 L1-d$-prefetch-misses ( 3.40x scaled) 5789421 L1-i$-loads ( 3.78x scaled) 29645 dTLB-load-misses ( 2.95x scaled) 461474 branch-loads ( 6.52x scaled) 7493 branch-load-misses ( 26.57x scaled) Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1246051927.2988.10.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 52c176cc683ec..3840a70f05b72 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -32,6 +32,7 @@ * Wu Fengguang <fengguang.wu@intel.com> * Mike Galbraith <efault@gmx.de> * Paul Mackerras <paulus@samba.org> + * Jaswinder Singh Rajput <jaswinder@kernel.org> * * Released under the GPL v2. (and only v2, not any later version) */ @@ -251,7 +252,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise) { double msecs = (double)count[0] / 1000000; - fprintf(stderr, " %14.6f %-20s", msecs, event_name(counter)); + fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); if (attrs[counter].type == PERF_TYPE_SOFTWARE && attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { @@ -265,7 +266,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise) static void abs_printout(int counter, u64 *count, u64 *noise) { - fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter)); + fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); if (runtime_cycles_avg && attrs[counter].type == PERF_TYPE_HARDWARE && @@ -295,7 +296,7 @@ static void print_counter(int counter) scaled = event_scaled_avg[counter]; if (scaled == -1) { - fprintf(stderr, " %14s %-20s\n", + fprintf(stderr, " %14s %-24s\n", "<not counted>", event_name(counter)); return; } @@ -306,8 +307,7 @@ static void print_counter(int counter) abs_printout(counter, count, noise); if (scaled) - fprintf(stderr, " (scaled from %.2f%%)", - (double) count[2] / count[1] * 100); + fprintf(stderr, " (%7.2fx scaled)", (double)count[1]/count[2]); fprintf(stderr, "\n"); } @@ -421,7 +421,6 @@ static void print_stat(int argc, const char **argv) for (counter = 0; counter < nr_counters; counter++) print_counter(counter); - fprintf(stderr, "\n"); fprintf(stderr, " %14.9f seconds time elapsed", (double)walltime_nsecs_avg/1e9); -- GitLab From a222ad1a4b2e3ca177a538482c99c519c1ce94d1 Mon Sep 17 00:00:00 2001 From: Karen Xie <kxie@chelsio.com> Date: Fri, 26 Jun 2009 15:17:29 -0700 Subject: [PATCH 0299/1002] [SCSI] cxgb3i: fix connection error when vlan is enabled There is a bug when VLAN is configured on the cxgb3 interface, the iscsi conn. would be denied with message "cxgb3i: NOT going through cxgbi device." This patch adds code to get the real egress net_device when vlan is configured. Signed-off-by: Karen Xie <kxie@chelsio.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> --- drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index 74369a3f963b6..c399f485aa7d1 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -13,6 +13,7 @@ #include <linux/inet.h> #include <linux/crypto.h> +#include <linux/if_vlan.h> #include <net/dst.h> #include <net/tcp.h> #include <scsi/scsi_cmnd.h> @@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) struct cxgb3i_adapter *snic; int i; + if (ndev->priv_flags & IFF_802_1Q_VLAN) + ndev = vlan_dev_real_dev(ndev); + read_lock(&cxgb3i_snic_rwlock); list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { for (i = 0; i < snic->hba_cnt; i++) { -- GitLab From f0a71eb820596bd8f6abf64beb4cb181edaa2341 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Sat, 27 Jun 2009 07:04:55 -0400 Subject: [PATCH 0300/1002] cifs: fix fh_mutex locking in cifs_reopen_file Fixes a regression caused by commit a6ce4932fbdbcd8f8e8c6df76812014351c32892 When this lock was converted to a mutex, the locks were turned into unlocks and vice-versa. Signed-off-by: Jeff Layton <jlayton@redhat.com> Acked-by: Shirish Pargaonkar <shirishp@us.ibm.com> Cc: Stable Tree <stable@kernel.org> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ebdbe62a829cf..97ce4bf89d152 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -493,9 +493,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush) return -EBADF; xid = GetXid(); - mutex_unlock(&pCifsFile->fh_mutex); + mutex_lock(&pCifsFile->fh_mutex); if (!pCifsFile->invalidHandle) { - mutex_lock(&pCifsFile->fh_mutex); + mutex_unlock(&pCifsFile->fh_mutex); rc = 0; FreeXid(xid); return rc; @@ -527,7 +527,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) if (full_path == NULL) { rc = -ENOMEM; reopen_error_exit: - mutex_lock(&pCifsFile->fh_mutex); + mutex_unlock(&pCifsFile->fh_mutex); FreeXid(xid); return rc; } @@ -569,14 +569,14 @@ static int cifs_reopen_file(struct file *file, bool can_flush) cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { - mutex_lock(&pCifsFile->fh_mutex); + mutex_unlock(&pCifsFile->fh_mutex); cFYI(1, ("cifs_open returned 0x%x", rc)); cFYI(1, ("oplock: %d", oplock)); } else { reopen_success: pCifsFile->netfid = netfid; pCifsFile->invalidHandle = false; - mutex_lock(&pCifsFile->fh_mutex); + mutex_unlock(&pCifsFile->fh_mutex); pCifsInode = CIFS_I(inode); if (pCifsInode) { if (can_flush) { -- GitLab From ff8a4bae459a9b6455504127fcb78fdbc8e50e4c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" <hpa@zytor.com> Date: Sat, 27 Jun 2009 12:22:27 -0700 Subject: [PATCH 0301/1002] Revert "x86: cap iomem_resource to addressable physical memory" This reverts commit 95ee14e4379c5e19c0897c872350570402014742. Mikael Petterson <mikepe@it.uu.se> reported that at least one of his systems will not boot as a result. We have ruled out the detection algorithm malfunctioning, so it is not a matter of producing the incorrect bitmasks; rather, something in the application of them fails. Revert the commit until we can root cause and correct this problem. -stable team: this means the underlying commit should be rejected. Reported-and-isolated-by: Mikael Petterson <mikpe@it.uu.se> Signed-off-by: H. Peter Anvin <hpa@zytor.com> LKML-Reference: <200906261559.n5QFxJH8027336@pilspetsen.it.uu.se> Cc: stable@kernel.org Cc: Grant Grundler <grundler@parisc-linux.org> --- arch/x86/kernel/cpu/common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6b26d4deada0c..f1961c07af9a6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -848,9 +848,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64) numa_add_cpu(smp_processor_id()); #endif - - /* Cap the iomem address space to what is addressable on all CPUs */ - iomem_resource.end &= (1ULL << c->x86_phys_bits) - 1; } #ifdef CONFIG_X86_64 -- GitLab From c276aca46d26aa2347320096f8ecdf5016795c14 Mon Sep 17 00:00:00 2001 From: vimal singh <vimalsingh@ti.com> Date: Sat, 27 Jun 2009 11:07:06 +0530 Subject: [PATCH 0302/1002] mtd: nand: fix build failure and incorrect return from omap_wait() We need to include jiffies.h manually in some cases, and the status returned from omap_wait() was broken in two separate ways. Also add cond_resched() to the loop. Signed-off-by: Vimal Singh <vimalsingh@ti.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/mtd/nand/omap2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 0cd76f89f4b0a..ebd07e95b8140 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -11,6 +11,8 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/sched.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> @@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); unsigned long timeo = jiffies; - int status, state = this->state; + int status = NAND_STATUS_FAIL, state = this->state; if (state == FL_ERASING) timeo += (HZ * 400) / 1000; @@ -556,8 +558,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) while (time_before(jiffies, timeo)) { status = __raw_readb(this->IO_ADDR_R); - if (!(status & 0x40)) + if (status & NAND_STATUS_READY) break; + cond_resched(); } return status; } -- GitLab From e244584fe3a5c20deddeca246548ac86dbc6e1d1 Mon Sep 17 00:00:00 2001 From: Izik Eidus <ieidus@redhat.com> Date: Wed, 10 Jun 2009 19:23:24 +0300 Subject: [PATCH 0303/1002] KVM: Fix dirty bit tracking for slots with large pages When slot is already allocated and being asked to be tracked we need to break the large pages. This code flush the mmu when someone ask a slot to start dirty bit tracking. Cc: stable@kernel.org Signed-off-by: Izik Eidus <ieidus@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- virt/kvm/kvm_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 764554350ed86..013a5b3e9f75c 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1194,6 +1194,8 @@ int __kvm_set_memory_region(struct kvm *kvm, if (!new.dirty_bitmap) goto out_free; memset(new.dirty_bitmap, 0, dirty_bytes); + if (old.npages) + kvm_arch_flush_shadow(kvm); } #endif /* not defined CONFIG_S390 */ -- GitLab From 29a4b9333bf9ffef12b3dd7cbf2e3dbe01152968 Mon Sep 17 00:00:00 2001 From: Avi Kivity <avi@redhat.com> Date: Tue, 19 May 2009 13:29:27 +0300 Subject: [PATCH 0304/1002] KVM: MMU: Allow 4K ptes with bit 7 (PAT) set Bit 7 is perfectly legal in the 4K page leve; it is used for the PAT. Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/mmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 5c3d6e81a7dc6..7030b5f911bff 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2157,7 +2157,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level) else /* 32 bits PSE 4MB page */ context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21); - context->rsvd_bits_mask[1][0] = ~0ull; + context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0]; break; case PT32E_ROOT_LEVEL: context->rsvd_bits_mask[0][2] = @@ -2170,7 +2170,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level) context->rsvd_bits_mask[1][1] = exb_bit_rsvd | rsvd_bits(maxphyaddr, 62) | rsvd_bits(13, 20); /* large page */ - context->rsvd_bits_mask[1][0] = ~0ull; + context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0]; break; case PT64_ROOT_LEVEL: context->rsvd_bits_mask[0][3] = exb_bit_rsvd | @@ -2186,7 +2186,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level) context->rsvd_bits_mask[1][1] = exb_bit_rsvd | rsvd_bits(maxphyaddr, 51) | rsvd_bits(13, 20); /* large page */ - context->rsvd_bits_mask[1][0] = ~0ull; + context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0]; break; } } -- GitLab From 84261923d3dddb766736023bead6fa07b7e218d5 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti <mtosatti@redhat.com> Date: Wed, 17 Jun 2009 10:53:47 -0300 Subject: [PATCH 0305/1002] KVM: protect concurrent make_all_cpus_request make_all_cpus_request contains a race condition which can trigger false request completed status, as follows: CPU0 CPU1 if (test_and_set_bit(req,&vcpu->requests)) .... if (test_and_set_bit(req,&vcpu->requests)) .. return proceed to smp_call_function_many(wait=1) Use a spinlock to serialize concurrent CPUs. Cc: stable@kernel.org Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- include/linux/kvm_host.h | 1 + virt/kvm/kvm_main.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index aacc5449f5863..16713dc672e42 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -125,6 +125,7 @@ struct kvm_kernel_irq_routing_entry { struct kvm { struct mutex lock; /* protects the vcpus array and APIC accesses */ spinlock_t mmu_lock; + spinlock_t requests_lock; struct rw_semaphore slots_lock; struct mm_struct *mm; /* userspace tied to this vm */ int nmemslots; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 013a5b3e9f75c..2884baf1d5f91 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -746,6 +746,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) cpumask_clear(cpus); me = get_cpu(); + spin_lock(&kvm->requests_lock); for (i = 0; i < KVM_MAX_VCPUS; ++i) { vcpu = kvm->vcpus[i]; if (!vcpu) @@ -762,6 +763,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req) smp_call_function_many(cpus, ack_flush, NULL, 1); else called = false; + spin_unlock(&kvm->requests_lock); put_cpu(); free_cpumask_var(cpus); return called; @@ -982,6 +984,7 @@ static struct kvm *kvm_create_vm(void) kvm->mm = current->mm; atomic_inc(&kvm->mm->mm_count); spin_lock_init(&kvm->mmu_lock); + spin_lock_init(&kvm->requests_lock); kvm_io_bus_init(&kvm->pio_bus); mutex_init(&kvm->lock); kvm_io_bus_init(&kvm->mmio_bus); -- GitLab From ffdfa071bd6fa8f5e5964569bef41e067540d424 Mon Sep 17 00:00:00 2001 From: Jes Sorensen <jes@sgi.com> Date: Wed, 17 Jun 2009 11:08:08 +0200 Subject: [PATCH 0306/1002] KVM: ia64: fix ia64 build due to missing kallsyms_lookup() and double export Fix problem with double export of certain symbols from vsprintf.c which we do not wish to export from the kvm-intel.ko module. In addition, we do not have access to kallsyms_lookup() from the module, so make sure to #undef CONFIG_KALLSYMS Signed-off-by: Jes Sorensen <jes@sgi.com> Acked-by: Xiantao Zhang <xiantao.zhang@intel.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/ia64/kvm/kvm_lib.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/ia64/kvm/kvm_lib.c b/arch/ia64/kvm/kvm_lib.c index a85cb611ecd7c..f1268b8e6f9e6 100644 --- a/arch/ia64/kvm/kvm_lib.c +++ b/arch/ia64/kvm/kvm_lib.c @@ -11,5 +11,11 @@ * */ #undef CONFIG_MODULES +#include <linux/module.h> +#undef CONFIG_KALLSYMS +#undef EXPORT_SYMBOL +#undef EXPORT_SYMBOL_GPL +#define EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_GPL(sym) #include "../../../lib/vsprintf.c" #include "../../../lib/ctype.c" -- GitLab From a3f9d3981cd82d65232b733eb792382237d686bd Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 18 Jun 2009 16:53:25 +0530 Subject: [PATCH 0307/1002] KVM: kvm/x86_emulate.c toggle_interruptibility() should be static toggle_interruptibility() is used only by same file, it should be static. Fixed following sparse warning : arch/x86/kvm/x86_emulate.c:1364:6: warning: symbol 'toggle_interruptibility' was not declared. Should it be static? Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/x86_emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index c1b6c232e02b1..616de4628d60d 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -1361,7 +1361,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt, return 0; } -void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask) +static void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask) { u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(ctxt->vcpu, mask); /* -- GitLab From ef50f7ac7e234f9696555e41eab3de69c3d86166 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger <borntraeger@de.ibm.com> Date: Tue, 23 Jun 2009 17:24:07 +0200 Subject: [PATCH 0308/1002] KVM: s390: Allow stfle instruction in the guest 2.6.31-rc introduced an architecture level set checker based on facility bits. e.g. if the kernel is compiled to run only on z9, several facility bits are checked very early and the kernel refuses to boot if a z9 specific facility is missing. Until now kvm on s390 did not implement the store facility extended (STFLE) instruction. A 2.6.31-rc kernel that was compiled for z9 or higher did not boot in kvm. This patch implements stfle. This patch should go in before 2.6.31. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/s390/include/asm/kvm_host.h | 4 +++- arch/s390/kvm/kvm-s390.c | 23 ++++++++++++++++++++++- arch/s390/kvm/priv.c | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index a27d0d5a6f868..1cd02f6073a06 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -99,7 +99,9 @@ struct kvm_s390_sie_block { __u8 reservedd0[48]; /* 0x00d0 */ __u64 gcr[16]; /* 0x0100 */ __u64 gbea; /* 0x0180 */ - __u8 reserved188[120]; /* 0x0188 */ + __u8 reserved188[24]; /* 0x0188 */ + __u32 fac; /* 0x01a0 */ + __u8 reserved1a4[92]; /* 0x01a4 */ } __attribute__((packed)); struct kvm_vcpu_stat { diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c18b21d6991ce..90d9d1ba258b0 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -25,6 +25,7 @@ #include <asm/lowcore.h> #include <asm/pgtable.h> #include <asm/nmi.h> +#include <asm/system.h> #include "kvm-s390.h" #include "gaccess.h" @@ -69,6 +70,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { NULL } }; +static unsigned long long *facilities; /* Section: not file related */ void kvm_arch_hardware_enable(void *garbage) @@ -288,6 +290,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin; vcpu->arch.sie_block->ecb = 2; vcpu->arch.sie_block->eca = 0xC1002001U; + vcpu->arch.sie_block->fac = (int) (long) facilities; hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, (unsigned long) vcpu); @@ -739,11 +742,29 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) static int __init kvm_s390_init(void) { - return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); + int ret; + ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); + if (ret) + return ret; + + /* + * guests can ask for up to 255+1 double words, we need a full page + * to hold the maximum amount of facilites. On the other hand, we + * only set facilities that are known to work in KVM. + */ + facilities = (unsigned long long *) get_zeroed_page(GFP_DMA); + if (!facilities) { + kvm_exit(); + return -ENOMEM; + } + stfle(facilities, 1); + facilities[0] &= 0xff00fff3f0700000ULL; + return 0; } static void __exit kvm_s390_exit(void) { + free_page((unsigned long) facilities); kvm_exit(); } diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 93ecd06e1a749..d426aac8095de 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -158,7 +158,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu) vcpu->stat.instruction_stfl++; /* only pass the facility bits, which we can handle */ - facility_list &= 0xfe00fff3; + facility_list &= 0xff00fff3; rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), &facility_list, sizeof(facility_list)); -- GitLab From e3c7cb6ad7191e92ba89d00a7ae5f5dd1ca0c214 Mon Sep 17 00:00:00 2001 From: Avi Kivity <avi@redhat.com> Date: Tue, 16 Jun 2009 14:19:52 +0300 Subject: [PATCH 0309/1002] KVM: VMX: Handle vmx instruction vmexits IF a guest tries to use vmx instructions, inject a #UD to let it know the instruction is not implemented, rather than crashing. This prevents guest userspace from crashing the guest kernel. Cc: stable@kernel.org Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/vmx.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e770bf349ec4f..356a0ce85c68d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3012,6 +3012,12 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 1; } +static int handle_vmx_insn(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +{ + kvm_queue_exception(vcpu, UD_VECTOR); + return 1; +} + static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); @@ -3198,6 +3204,15 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu, [EXIT_REASON_HLT] = handle_halt, [EXIT_REASON_INVLPG] = handle_invlpg, [EXIT_REASON_VMCALL] = handle_vmcall, + [EXIT_REASON_VMCLEAR] = handle_vmx_insn, + [EXIT_REASON_VMLAUNCH] = handle_vmx_insn, + [EXIT_REASON_VMPTRLD] = handle_vmx_insn, + [EXIT_REASON_VMPTRST] = handle_vmx_insn, + [EXIT_REASON_VMREAD] = handle_vmx_insn, + [EXIT_REASON_VMRESUME] = handle_vmx_insn, + [EXIT_REASON_VMWRITE] = handle_vmx_insn, + [EXIT_REASON_VMOFF] = handle_vmx_insn, + [EXIT_REASON_VMON] = handle_vmx_insn, [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold, [EXIT_REASON_APIC_ACCESS] = handle_apic_access, [EXIT_REASON_WBINVD] = handle_wbinvd, -- GitLab From 9e6996240afcbe61682eab8eeaeb65c34333164d Mon Sep 17 00:00:00 2001 From: Amit Shah <amit.shah@redhat.com> Date: Mon, 15 Jun 2009 13:25:34 +0530 Subject: [PATCH 0310/1002] KVM: Ignore reads to K7 EVNTSEL MSRs In commit 7fe29e0faacb650d31b9e9f538203a157bec821d we ignored the reads to the P6 EVNTSEL MSRs. That fixed crashes on Intel machines. Ignore the reads to K7 EVNTSEL MSRs as well to fix this on AMD hosts. This fixes Kaspersky antivirus crashing Windows guests on AMD hosts. Signed-off-by: Amit Shah <amit.shah@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 249540f985132..fe5474aec41a0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -898,6 +898,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_VM_HSAVE_PA: case MSR_P6_EVNTSEL0: case MSR_P6_EVNTSEL1: + case MSR_K7_EVNTSEL0: data = 0; break; case MSR_MTRRcap: -- GitLab From bde892232532ed522bb56b04576d07f91e59b3c7 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 20 May 2009 09:59:35 +0530 Subject: [PATCH 0311/1002] KVM: shut up uninit compiler warning in paging_tmpl.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dixes compilation warning: CC arch/x86/kernel/io_delay.o arch/x86/kvm/paging_tmpl.h: In function ‘paging64_fetch’: arch/x86/kvm/paging_tmpl.h:279: warning: ‘sptep’ may be used uninitialized in this function arch/x86/kvm/paging_tmpl.h: In function ‘paging32_fetch’: arch/x86/kvm/paging_tmpl.h:279: warning: ‘sptep’ may be used uninitialized in this function warning is bogus (always have a least one level), but need to shut the compiler up. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/paging_tmpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 258e4591e1ca0..67785f635399f 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -281,7 +281,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, { unsigned access = gw->pt_access; struct kvm_mmu_page *shadow_page; - u64 spte, *sptep; + u64 spte, *sptep = NULL; int direct; gfn_t table_gfn; int r; -- GitLab From c3043569dc8fbe9228b76174f15d1a7152c48a20 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Sat, 27 Jun 2009 23:49:09 +0530 Subject: [PATCH 0312/1002] perf stat: Micro-optimize the code: memcpy is only required if no event is selected and !null_run Set attrs and nr_counters if no event is selected and !null_run. Setting of attrs should depend on number of counters, so we need to memcpy only for sizeof(default_attrs) Also set nr_counters as ARRAY_SIZE(default_attrs) in place of hardcoded value. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1246126749.32198.16.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3840a70f05b72..3e5ea4e2e5fd9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -46,7 +46,7 @@ #include <sys/prctl.h> #include <math.h> -static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { +static struct perf_counter_attr default_attrs[] = { { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, @@ -477,16 +477,17 @@ int cmd_stat(int argc, const char **argv, const char *prefix) { int status; - memcpy(attrs, default_attrs, sizeof(attrs)); - argc = parse_options(argc, argv, options, stat_usage, 0); if (!argc) usage_with_options(stat_usage, options); if (run_count <= 0 || run_count > MAX_RUN) usage_with_options(stat_usage, options); - if (!null_run && !nr_counters) - nr_counters = 8; + /* Set attrs and nr_counters if no event is selected and !null_run */ + if (!null_run && !nr_counters) { + memcpy(attrs, default_attrs, sizeof(default_attrs)); + nr_counters = ARRAY_SIZE(default_attrs); + } nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); assert(nr_cpus <= MAX_NR_CPUS); -- GitLab From 46690f3718d95e9bb712b6f2b5c869f8494521de Mon Sep 17 00:00:00 2001 From: Mimi Zohar <zohar@linux.vnet.ibm.com> Date: Fri, 26 Jun 2009 11:24:05 -0400 Subject: [PATCH 0313/1002] integrity: ima mq_open imbalance msg fix This patch fixes an imbalance message as reported by Sanchin Sant. As we don't need to measure the message queue, just increment the counters. Reported-by: Sanchin Sant <sanchinp@in.ibm.com> Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org> --- ipc/mqueue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e35ba2c3a8d77..c5e68adc67324 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -32,6 +32,7 @@ #include <linux/nsproxy.h> #include <linux/pid.h> #include <linux/ipc_namespace.h> +#include <linux/ima.h> #include <net/sock.h> #include "util.h" @@ -733,6 +734,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, error = PTR_ERR(filp); goto out_putfd; } + ima_counts_get(filp); fd_install(fd, filp); goto out_upsem; -- GitLab From 79b854c549c62c54fa27f87e04465c01db889f8d Mon Sep 17 00:00:00 2001 From: Mimi Zohar <zohar@linux.vnet.ibm.com> Date: Fri, 26 Jun 2009 11:25:00 -0400 Subject: [PATCH 0314/1002] integrity: ima audit hash_exists fix Audit the file name, not the template name. Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org> --- security/integrity/ima/ima_queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 7ec94314ac0ca..a0880e9c8e054 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -134,7 +134,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, } out: mutex_unlock(&ima_extend_list_mutex); - integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name, + integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, + entry->template.file_name, op, audit_cause, result, audit_info); return result; } -- GitLab From 94e5d714f604d4cb4cb13163f01ede278e69258b Mon Sep 17 00:00:00 2001 From: Mimi Zohar <zohar@linux.vnet.ibm.com> Date: Fri, 26 Jun 2009 14:05:27 -0400 Subject: [PATCH 0315/1002] integrity: add ima_counts_put (updated) This patch fixes an imbalance message as reported by J.R. Okajima. The IMA file counters are incremented in ima_path_check. If the actual open fails, such as ETXTBSY, decrement the counters to prevent unnecessary imbalance messages. Reported-by: J.R. Okajima <hooanon05@yahoo.co.jp> Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org> --- fs/namei.c | 7 +++++++ include/linux/ima.h | 6 ++++++ security/integrity/ima/ima_main.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 5b961eb71cbf9..f3c5b278895a0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1761,6 +1761,10 @@ struct file *do_filp_open(int dfd, const char *pathname, goto exit; } filp = nameidata_to_filp(&nd, open_flag); + if (IS_ERR(filp)) + ima_counts_put(&nd.path, + acc_mode & (MAY_READ | MAY_WRITE | + MAY_EXEC)); mnt_drop_write(nd.path.mnt); if (nd.root.mnt) path_put(&nd.root); @@ -1817,6 +1821,9 @@ struct file *do_filp_open(int dfd, const char *pathname, goto exit; } filp = nameidata_to_filp(&nd, open_flag); + if (IS_ERR(filp)) + ima_counts_put(&nd.path, + acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); /* * It is now safe to drop the mnt write * because the filp has had a write taken diff --git a/include/linux/ima.h b/include/linux/ima.h index b1b827d091a99..0e3f2a4c25f6e 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -24,6 +24,7 @@ extern int ima_path_check(struct path *path, int mask, int update_counts); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern void ima_counts_get(struct file *file); +extern void ima_counts_put(struct path *path, int mask); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -60,5 +61,10 @@ static inline void ima_counts_get(struct file *file) { return; } + +static inline void ima_counts_put(struct path *path, int mask) +{ + return; +} #endif /* CONFIG_IMA_H */ #endif /* _LINUX_IMA_H */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 6f611874d10e9..101c512564ec6 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -238,7 +238,34 @@ static int process_measurement(struct file *file, const unsigned char *filename, } /* - * ima_opens_get - increment file counts + * ima_counts_put - decrement file counts + * + * File counts are incremented in ima_path_check. On file open + * error, such as ETXTBSY, decrement the counts to prevent + * unnecessary imbalance messages. + */ +void ima_counts_put(struct path *path, int mask) +{ + struct inode *inode = path->dentry->d_inode; + struct ima_iint_cache *iint; + + if (!ima_initialized || !S_ISREG(inode->i_mode)) + return; + iint = ima_iint_find_insert_get(inode); + if (!iint) + return; + + mutex_lock(&iint->mutex); + iint->opencount--; + if ((mask & MAY_WRITE) || (mask == 0)) + iint->writecount--; + else if (mask & (MAY_READ | MAY_EXEC)) + iint->readcount--; + mutex_unlock(&iint->mutex); +} + +/* + * ima_counts_get - increment file counts * * - for IPC shm and shmat file. * - for nfsd exported files. -- GitLab From bd46cb6cf11867130a41ea9546dd65688b71f3c2 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde <ajitk@serverengines.com> Date: Fri, 26 Jun 2009 02:51:07 +0000 Subject: [PATCH 0316/1002] be2net: Fix to avoid a crash seen on PPC with LRO and Jumbo frames. While testing the driver on PPC, we ran into a crash with LRO, Jumbo frames. With CONFIG_PPC_64K_PAGES configured (a default in PPC), MAX_SKB_FRAGS drops to 3 and we were crossing the array limits on skb_shinfo(skb)->frags[]. Now we coalesce the frags from the same physical page into one slot in skb_shinfo(skb)->frags[] and go to the next index when the frag is from different physical page. This patch is against the net-2.6 tree. Signed-off-by: Ajit Khaparde <ajitk@serverengines.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/benet/be.h | 2 +- drivers/net/benet/be_ethtool.c | 4 +-- drivers/net/benet/be_main.c | 45 ++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index f703758f0a6e4..5b4bf3d2cdc2e 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -73,7 +73,7 @@ static inline char *nic_name(struct pci_dev *pdev) #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) #define BE_MAX_LRO_DESCRIPTORS 16 -#define BE_MAX_FRAGS_PER_FRAME 16 +#define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS)) struct be_dma_mem { void *va; diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 9592f22e4c8c2..cccc5419ad72a 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -162,8 +162,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) return -EINVAL; adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal > MAX_SKB_FRAGS) - adapter->max_rx_coal = MAX_SKB_FRAGS - 1; + if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME) + adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; /* if AIC is being turned on now, start with an EQD of 0 */ if (rx_eq->enable_aic == 0 && diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 66c10c87f5175..308eb09ca56bb 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -666,7 +666,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, { struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_rx_page_info *page_info; - u16 rxq_idx, i, num_rcvd; + u16 rxq_idx, i, num_rcvd, j; u32 pktsize, hdr_len, curr_frag_len; u8 *start; @@ -709,22 +709,33 @@ static void skb_fill_rx_data(struct be_adapter *adapter, /* More frags present for this completion */ pktsize -= curr_frag_len; /* account for above copied frag */ - for (i = 1; i < num_rcvd; i++) { + for (i = 1, j = 0; i < num_rcvd; i++) { index_inc(&rxq_idx, rxq->len); page_info = get_rx_page_info(adapter, rxq_idx); curr_frag_len = min(pktsize, rx_frag_size); - skb_shinfo(skb)->frags[i].page = page_info->page; - skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; - skb_shinfo(skb)->frags[i].size = curr_frag_len; + /* Coalesce all frags from the same physical page in one slot */ + if (page_info->page_offset == 0) { + /* Fresh page */ + j++; + skb_shinfo(skb)->frags[j].page = page_info->page; + skb_shinfo(skb)->frags[j].page_offset = + page_info->page_offset; + skb_shinfo(skb)->frags[j].size = 0; + skb_shinfo(skb)->nr_frags++; + } else { + put_page(page_info->page); + } + + skb_shinfo(skb)->frags[j].size += curr_frag_len; skb->len += curr_frag_len; skb->data_len += curr_frag_len; - skb_shinfo(skb)->nr_frags++; pktsize -= curr_frag_len; memset(page_info, 0, sizeof(*page_info)); } + BUG_ON(j > MAX_SKB_FRAGS); done: be_rx_stats_update(adapter, pktsize, num_rcvd); @@ -786,7 +797,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; struct be_queue_info *rxq = &adapter->rx_obj.q; u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; - u16 i, rxq_idx = 0, vid; + u16 i, rxq_idx = 0, vid, j; num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); @@ -794,20 +805,28 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); remaining = pkt_size; - for (i = 0; i < num_rcvd; i++) { + for (i = 0, j = -1; i < num_rcvd; i++) { page_info = get_rx_page_info(adapter, rxq_idx); curr_frag_len = min(remaining, rx_frag_size); - rx_frags[i].page = page_info->page; - rx_frags[i].page_offset = page_info->page_offset; - rx_frags[i].size = curr_frag_len; - remaining -= curr_frag_len; + /* Coalesce all frags from the same physical page in one slot */ + if (i == 0 || page_info->page_offset == 0) { + /* First frag or Fresh page */ + j++; + rx_frags[j].page = page_info->page; + rx_frags[j].page_offset = page_info->page_offset; + rx_frags[j].size = 0; + } else { + put_page(page_info->page); + } + rx_frags[j].size += curr_frag_len; + remaining -= curr_frag_len; index_inc(&rxq_idx, rxq->len); - memset(page_info, 0, sizeof(*page_info)); } + BUG_ON(j > MAX_SKB_FRAGS); if (likely(!vlanf)) { lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, -- GitLab From 684a88429c5ab04d8b1894de9a1ef62de6f601b7 Mon Sep 17 00:00:00 2001 From: Tony Vroon <tony@linx.net> Date: Fri, 26 Jun 2009 09:27:50 +0100 Subject: [PATCH 0317/1002] ALSA: hda - Line In for Acer Inspire 6530G model The Line In connector is set up as PIN_IN by default, using VREF_HIZ. It is connected to both ADCs, so add it to both input selectors. Also add the ability to use the input mix (on a SoundBlaster one would call this "What You Hear"). Signed-off-by: Tony Vroon <tony@linx.net> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2ed514030e75e..08846d222cbe1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1569,18 +1569,22 @@ static struct hda_input_mux alc888_2_capture_sources[2] = { static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = { /* Interal mic only available on one ADC */ { - .num_items = 3, + .num_items = 5, .items = { { "Ext Mic", 0x0 }, + { "Line In", 0x2 }, { "CD", 0x4 }, + { "Input Mix", 0xa }, { "Int Mic", 0xb }, }, }, { - .num_items = 2, + .num_items = 4, .items = { { "Ext Mic", 0x0 }, + { "Line In", 0x2 }, { "CD", 0x4 }, + { "Input Mix", 0xa }, }, } }; @@ -8209,6 +8213,8 @@ static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), -- GitLab From c2a30d711852e4f39c8a79135b3caa701f7a8e02 Mon Sep 17 00:00:00 2001 From: Ondrej Zary <linux@rainbow-software.org> Date: Sat, 27 Jun 2009 16:17:08 +0200 Subject: [PATCH 0318/1002] ALSA: cmi8330: fix MPU-401 PnP init copy&paste bug Fix copy&paste bug in PnP MPU-401 initialization. Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Cc: <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/isa/cmi8330.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index de83608719ea2..3ee0269e5bd08 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -338,7 +338,7 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, return -EBUSY; acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->play == NULL) + if (acard->mpu == NULL) return -EBUSY; pdev = acard->cap; -- GitLab From ec5a36f94e7ca4b1f28ae4dd135cd415a704e772 Mon Sep 17 00:00:00 2001 From: Pekka Enberg <penberg@cs.helsinki.fi> Date: Mon, 29 Jun 2009 09:57:10 +0300 Subject: [PATCH 0319/1002] SLAB: Fix lockdep annotations Commit 8429db5... ("slab: setup cpu caches later on when interrupts are enabled") broke mm/slab.c lockdep annotations: [ 11.554715] ============================================= [ 11.555249] [ INFO: possible recursive locking detected ] [ 11.555560] 2.6.31-rc1 #896 [ 11.555861] --------------------------------------------- [ 11.556127] udevd/1899 is trying to acquire lock: [ 11.556436] (&nc->lock){-.-...}, at: [<ffffffff810c337f>] kmem_cache_free+0xcd/0x25b [ 11.557101] [ 11.557102] but task is already holding lock: [ 11.557706] (&nc->lock){-.-...}, at: [<ffffffff810c3cd0>] kfree+0x137/0x292 [ 11.558109] [ 11.558109] other info that might help us debug this: [ 11.558720] 2 locks held by udevd/1899: [ 11.558983] #0: (&nc->lock){-.-...}, at: [<ffffffff810c3cd0>] kfree+0x137/0x292 [ 11.559734] #1: (&parent->list_lock){-.-...}, at: [<ffffffff810c36c7>] __drain_alien_cache+0x3b/0xbd [ 11.560442] [ 11.560443] stack backtrace: [ 11.561009] Pid: 1899, comm: udevd Not tainted 2.6.31-rc1 #896 [ 11.561276] Call Trace: [ 11.561632] [<ffffffff81065ed6>] __lock_acquire+0x15ec/0x168f [ 11.561901] [<ffffffff81065f60>] ? __lock_acquire+0x1676/0x168f [ 11.562171] [<ffffffff81063c52>] ? trace_hardirqs_on_caller+0x113/0x13e [ 11.562490] [<ffffffff8150c337>] ? trace_hardirqs_on_thunk+0x3a/0x3f [ 11.562807] [<ffffffff8106603a>] lock_acquire+0xc1/0xe5 [ 11.563073] [<ffffffff810c337f>] ? kmem_cache_free+0xcd/0x25b [ 11.563385] [<ffffffff8150c8fc>] _spin_lock+0x31/0x66 [ 11.563696] [<ffffffff810c337f>] ? kmem_cache_free+0xcd/0x25b [ 11.563964] [<ffffffff810c337f>] kmem_cache_free+0xcd/0x25b [ 11.564235] [<ffffffff8109bf8c>] ? __free_pages+0x1b/0x24 [ 11.564551] [<ffffffff810c3564>] slab_destroy+0x57/0x5c [ 11.564860] [<ffffffff810c3641>] free_block+0xd8/0x123 [ 11.565126] [<ffffffff810c372e>] __drain_alien_cache+0xa2/0xbd [ 11.565441] [<ffffffff810c3ce5>] kfree+0x14c/0x292 [ 11.565752] [<ffffffff8144a007>] skb_release_data+0xc6/0xcb [ 11.566020] [<ffffffff81449cf0>] __kfree_skb+0x19/0x86 [ 11.566286] [<ffffffff81449d88>] consume_skb+0x2b/0x2d [ 11.566631] [<ffffffff8144cbe0>] skb_free_datagram+0x14/0x3a [ 11.566901] [<ffffffff81462eef>] netlink_recvmsg+0x164/0x258 [ 11.567170] [<ffffffff81443461>] sock_recvmsg+0xe5/0xfe [ 11.567486] [<ffffffff810ab063>] ? might_fault+0xaf/0xb1 [ 11.567802] [<ffffffff81053a78>] ? autoremove_wake_function+0x0/0x38 [ 11.568073] [<ffffffff810d84ca>] ? core_sys_select+0x3d/0x2b4 [ 11.568378] [<ffffffff81065f60>] ? __lock_acquire+0x1676/0x168f [ 11.568693] [<ffffffff81442dc1>] ? sockfd_lookup_light+0x1b/0x54 [ 11.568961] [<ffffffff81444416>] sys_recvfrom+0xa3/0xf8 [ 11.569228] [<ffffffff81063c8a>] ? trace_hardirqs_on+0xd/0xf [ 11.569546] [<ffffffff8100af2b>] system_call_fastpath+0x16/0x1b# Fix that up. Closes-bug: http://bugzilla.kernel.org/show_bug.cgi?id=13654 Tested-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> --- mm/slab.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 5241b6598ba38..7b5d4deacfcd9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1544,9 +1544,6 @@ void __init kmem_cache_init(void) } g_cpucache_up = EARLY; - - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); } void __init kmem_cache_init_late(void) @@ -1563,6 +1560,9 @@ void __init kmem_cache_init_late(void) /* Done! */ g_cpucache_up = FULL; + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* * Register a cpu startup notifier callback that initializes * cpu_cache_get for all new cpus -- GitLab From 9230ccb1071d2d7e4ecb6314e67203b9f7f08140 Mon Sep 17 00:00:00 2001 From: Yan Li <yan.i.li@intel.com> Date: Sun, 28 Jun 2009 22:30:56 -0700 Subject: [PATCH 0320/1002] Input: i8042 - more reset quirks for MSI Wind-clone netbooks When testing Moblin on various netbooks, we've got reports that many MSI Wind clones need the i8042 reset quirks for the keyboard and/or touchpad's proper function. Signed-off-by: Yan Li <yan.i.li@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/serio/i8042-x86ia64io.h | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index fb8a3cd3ffd0a..924e8ed7f2cf7 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -392,6 +392,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), }, }, + { + .ident = "Acer Aspire One 150", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), + }, + }, + { + .ident = "Advent 4211", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), + DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), + }, + }, + { + .ident = "Medion Akoya Mini E1210", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), + }, + }, + { + .ident = "Mivvy M310", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), + DMI_MATCH(DMI_PRODUCT_NAME, "N10"), + }, + }, { } }; -- GitLab From c413ec446188ae53276eb60a60311b430448c6b0 Mon Sep 17 00:00:00 2001 From: Ping Cheng <pingc@wacom.com> Date: Sun, 28 Jun 2009 22:50:58 -0700 Subject: [PATCH 0321/1002] Input: wacom - add DTF720a support and fix rotation on Intuos3 This patch adds DTF720a support and fixes an Intuos3 rotation pen out-proximity bug. Signed-off-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/tablet/wacom_wac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 38bf86384aeba..c896d6a21b7ee 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_TOUCH, 0); wacom_report_abs(wcombo, ABS_WHEEL, 0); + if (wacom->features->type >= INTUOS3S) + wacom_report_abs(wcombo, ABS_Z, 0); } wacom_report_key(wcombo, wacom->tool[idx], 0); wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ @@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = { { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, + { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, @@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, -- GitLab From 00b8ac409cad653137f087e3ff69c020174cbc15 Mon Sep 17 00:00:00 2001 From: David Brownell <dbrownell@users.sourceforge.net> Date: Sun, 28 Jun 2009 22:30:56 -0700 Subject: [PATCH 0322/1002] Input: dm355evm_keys - fix kconfig symbol names The keypad driver for the DM355 EVM got slightly broken as it merged, since it moved from input/keyboard to input/misc and its Kconfig symbol changed. This patch copes with the changed Kconfig symbol. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/mfd/dm355evm_msp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 7ac12cb0be4a7..5b6e58a3ba46c 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -32,8 +32,7 @@ * This driver was tested with firmware revision A4. */ -#if defined(CONFIG_KEYBOARD_DM355EVM) \ - || defined(CONFIG_KEYBOARD_DM355EVM_MODULE) +#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE) #define msp_has_keyboard() true #else #define msp_has_keyboard() false -- GitLab From ca865a77b5949f5c403e0f13de5a5a9cd499a11e Mon Sep 17 00:00:00 2001 From: Jani Nikula <ext-jani.1.nikula@nokia.com> Date: Sun, 28 Jun 2009 22:38:44 -0700 Subject: [PATCH 0323/1002] Input: gpio-keys - revert 'change timer to workqueue' This reverts commit 0b346838c5862bfe911432956a106d602535d030. This commit breaks GPIO debouncing by replacing the original mod_timer with schedule_delayed_work in the interrupt handler. The latter does not kick the timer further on GPIO line changes as it should to perform debouncing. Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/keyboard/gpio_keys.c | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2157cd7de00ce..9767213b6c8f1 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -22,14 +22,13 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/gpio_keys.h> -#include <linux/workqueue.h> #include <asm/gpio.h> struct gpio_button_data { struct gpio_keys_button *button; struct input_dev *input; - struct delayed_work work; + struct timer_list timer; }; struct gpio_keys_drvdata { @@ -37,10 +36,8 @@ struct gpio_keys_drvdata { struct gpio_button_data data[0]; }; -static void gpio_keys_report_event(struct work_struct *work) +static void gpio_keys_report_event(struct gpio_button_data *bdata) { - struct gpio_button_data *bdata = - container_of(work, struct gpio_button_data, work.work); struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; @@ -50,17 +47,25 @@ static void gpio_keys_report_event(struct work_struct *work) input_sync(input); } +static void gpio_check_button(unsigned long _data) +{ + struct gpio_button_data *data = (struct gpio_button_data *)_data; + + gpio_keys_report_event(data); +} + static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; - unsigned long delay; BUG_ON(irq != gpio_to_irq(button->gpio)); - delay = button->debounce_interval ? - msecs_to_jiffies(button->debounce_interval) : 0; - schedule_delayed_work(&bdata->work, delay); + if (button->debounce_interval) + mod_timer(&bdata->timer, + jiffies + msecs_to_jiffies(button->debounce_interval)); + else + gpio_keys_report_event(bdata); return IRQ_HANDLED; } @@ -107,7 +112,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) bdata->input = input; bdata->button = button; - INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); + setup_timer(&bdata->timer, + gpio_check_button, (unsigned long)bdata); error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); if (error < 0) { @@ -166,7 +172,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); - cancel_delayed_work_sync(&ddata->data[i].work); + if (pdata->buttons[i].debounce_interval) + del_timer_sync(&ddata->data[i].timer); gpio_free(pdata->buttons[i].gpio); } @@ -190,7 +197,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); free_irq(irq, &ddata->data[i]); - cancel_delayed_work_sync(&ddata->data[i].work); + if (pdata->buttons[i].debounce_interval) + del_timer_sync(&ddata->data[i].timer); gpio_free(pdata->buttons[i].gpio); } -- GitLab From da0d03fe6cecde837f113a8a587f5a872d0fade0 Mon Sep 17 00:00:00 2001 From: Jani Nikula <ext-jani.1.nikula@nokia.com> Date: Sun, 28 Jun 2009 22:38:56 -0700 Subject: [PATCH 0324/1002] Input: gpio-keys - avoid possibility of sleeping in timer function The gpio_get_value function may sleep, so it should not be called in a timer function. Move gpio_get_value calls to workqueue. Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/keyboard/gpio_keys.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 9767213b6c8f1..efed0c9e242ed 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/gpio_keys.h> +#include <linux/workqueue.h> #include <asm/gpio.h> @@ -29,6 +30,7 @@ struct gpio_button_data { struct gpio_keys_button *button; struct input_dev *input; struct timer_list timer; + struct work_struct work; }; struct gpio_keys_drvdata { @@ -36,8 +38,10 @@ struct gpio_keys_drvdata { struct gpio_button_data data[0]; }; -static void gpio_keys_report_event(struct gpio_button_data *bdata) +static void gpio_keys_report_event(struct work_struct *work) { + struct gpio_button_data *bdata = + container_of(work, struct gpio_button_data, work); struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; @@ -47,11 +51,11 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) input_sync(input); } -static void gpio_check_button(unsigned long _data) +static void gpio_keys_timer(unsigned long _data) { struct gpio_button_data *data = (struct gpio_button_data *)_data; - gpio_keys_report_event(data); + schedule_work(&data->work); } static irqreturn_t gpio_keys_isr(int irq, void *dev_id) @@ -65,7 +69,7 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(button->debounce_interval)); else - gpio_keys_report_event(bdata); + schedule_work(&bdata->work); return IRQ_HANDLED; } @@ -113,7 +117,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) bdata->input = input; bdata->button = button; setup_timer(&bdata->timer, - gpio_check_button, (unsigned long)bdata); + gpio_keys_timer, (unsigned long)bdata); + INIT_WORK(&bdata->work, gpio_keys_report_event); error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); if (error < 0) { @@ -174,6 +179,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); if (pdata->buttons[i].debounce_interval) del_timer_sync(&ddata->data[i].timer); + cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } @@ -199,6 +205,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) free_irq(irq, &ddata->data[i]); if (pdata->buttons[i].debounce_interval) del_timer_sync(&ddata->data[i].timer); + cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } -- GitLab From cb589529f74d69abc111887b45308f333f950ade Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov <dmitry.torokhov@gmail.com> Date: Mon, 29 Jun 2009 00:00:52 -0700 Subject: [PATCH 0325/1002] Input: arrange keyboards alphabetically Hopefully it will reduce conflicts when merging patches. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/keyboard/Kconfig | 291 ++++++++++++++++---------------- drivers/input/keyboard/Makefile | 32 ++-- 2 files changed, 161 insertions(+), 162 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9d8f796c67452..d2df1030675ab 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD if INPUT_KEYBOARD +config KEYBOARD_AAED2000 + tristate "AAED-2000 keyboard" + depends on MACH_AAED2000 + select INPUT_POLLDEV + default y + help + Say Y here to enable the keyboard on the Agilent AAED-2000 + development board. + + To compile this driver as a module, choose M here: the + module will be called aaed2000_kbd. + +config KEYBOARD_AMIGA + tristate "Amiga keyboard" + depends on AMIGA + help + Say Y here if you are running Linux on any AMIGA and have a keyboard + attached. + + To compile this driver as a module, choose M here: the + module will be called amikbd. + +config ATARI_KBD_CORE + bool + +config KEYBOARD_ATARI + tristate "Atari keyboard" + depends on ATARI + select ATARI_KBD_CORE + help + Say Y here if you are running Linux on any Atari and have a keyboard + attached. + + To compile this driver as a module, choose M here: the + module will be called atakbd. + config KEYBOARD_ATKBD tristate "AT keyboard" if EMBEDDED || !X86 default y @@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES right-hand column will be interpreted as the key shown in the left-hand column. -config KEYBOARD_SUNKBD - tristate "Sun Type 4 and Type 5 keyboard" - select SERIO - help - Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, - connected either to the Sun keyboard connector or to an serial - (RS-232) port via a simple adapter. - - To compile this driver as a module, choose M here: the - module will be called sunkbd. - -config KEYBOARD_LKKBD - tristate "DECstation/VAXstation LK201/LK401 keyboard" - select SERIO - help - Say Y here if you want to use a LK201 or LK401 style serial - keyboard. This keyboard is also useable on PCs if you attach - it with the inputattach program. The connector pinout is - described within lkkbd.c. - - To compile this driver as a module, choose M here: the - module will be called lkkbd. - -config KEYBOARD_LOCOMO - tristate "LoCoMo Keyboard Support" - depends on SHARP_LOCOMO && INPUT_KEYBOARD - help - Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA - - To compile this driver as a module, choose M here: the - module will be called locomokbd. - -config KEYBOARD_XTKBD - tristate "XT keyboard" - select SERIO - help - Say Y here if you want to use the old IBM PC/XT keyboard (or - compatible) on your system. This is only possible with a - parallel port keyboard adapter, you cannot connect it to the - keyboard port on a PC that runs Linux. - - To compile this driver as a module, choose M here: the - module will be called xtkbd. - -config KEYBOARD_NEWTON - tristate "Newton keyboard" - select SERIO - help - Say Y here if you have a Newton keyboard on a serial port. - - To compile this driver as a module, choose M here: the - module will be called newtonkbd. - -config KEYBOARD_STOWAWAY - tristate "Stowaway keyboard" - select SERIO +config KEYBOARD_BFIN + tristate "Blackfin BF54x keypad support" + depends on (BF54x && !BF544) help - Say Y here if you have a Stowaway keyboard on a serial port. - Stowaway compatible keyboards like Dicota Input-PDA keyboard - are also supported by this driver. + Say Y here if you want to use the BF54x keypad. To compile this driver as a module, choose M here: the - module will be called stowaway. + module will be called bf54x-keys. config KEYBOARD_CORGI tristate "Corgi keyboard" @@ -143,61 +124,41 @@ config KEYBOARD_CORGI To compile this driver as a module, choose M here: the module will be called corgikbd. -config KEYBOARD_SPITZ - tristate "Spitz keyboard" - depends on PXA_SHARPSL - default y +config KEYBOARD_LKKBD + tristate "DECstation/VAXstation LK201/LK401 keyboard" + select SERIO help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. + Say Y here if you want to use a LK201 or LK401 style serial + keyboard. This keyboard is also useable on PCs if you attach + it with the inputattach program. The connector pinout is + described within lkkbd.c. To compile this driver as a module, choose M here: the - module will be called spitzkbd. + module will be called lkkbd. -config KEYBOARD_TOSA - tristate "Tosa keyboard" - depends on MACH_TOSA - default y +config KEYBOARD_EP93XX + tristate "EP93xx Matrix Keypad support" + depends on ARCH_EP93XX help - Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) + Say Y here to enable the matrix keypad on the Cirrus EP93XX. To compile this driver as a module, choose M here: the - module will be called tosakbd. - -config KEYBOARD_TOSA_USE_EXT_KEYCODES - bool "Tosa keyboard: use extended keycodes" - depends on KEYBOARD_TOSA - default n - help - Say Y here to enable the tosa keyboard driver to generate extended - (>= 127) keycodes. Be aware, that they can't be correctly interpreted - by either console keyboard driver or by Kdrive keybd driver. - - Say Y only if you know, what you are doing! + module will be called ep93xx_keypad. -config KEYBOARD_AMIGA - tristate "Amiga keyboard" - depends on AMIGA +config KEYBOARD_GPIO + tristate "GPIO Buttons" + depends on GENERIC_GPIO help - Say Y here if you are running Linux on any AMIGA and have a keyboard - attached. - - To compile this driver as a module, choose M here: the - module will be called amikbd. - -config ATARI_KBD_CORE - bool + This driver implements support for buttons connected + to GPIO pins of various CPUs (and some other chips). -config KEYBOARD_ATARI - tristate "Atari keyboard" - depends on ATARI - select ATARI_KBD_CORE - help - Say Y here if you are running Linux on any Atari and have a keyboard - attached. + Say Y here if your device has buttons connected + directly to such GPIO pins. Your board-specific + setup logic must also provide a platform device, + with configuration data saying which GPIOs are used. To compile this driver as a module, choose M here: the - module will be called atakbd. + module will be called gpio-keys. config KEYBOARD_HIL_OLD tristate "HP HIL keyboard support (simple driver)" @@ -261,14 +222,33 @@ config KEYBOARD_LM8323 To compile this driver as a module, choose M here: the module will be called lm8323. -config KEYBOARD_OMAP - tristate "TI OMAP keypad support" - depends on (ARCH_OMAP1 || ARCH_OMAP2) +config KEYBOARD_LOCOMO + tristate "LoCoMo Keyboard Support" + depends on SHARP_LOCOMO help - Say Y here if you want to use the OMAP keypad. + Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA To compile this driver as a module, choose M here: the - module will be called omap-keypad. + module will be called locomokbd. + +config KEYBOARD_MAPLE + tristate "Maple bus keyboard" + depends on SH_DREAMCAST && MAPLE + help + Say Y here if you have a Dreamcast console running Linux and have + a keyboard attached to its Maple bus. + + To compile this driver as a module, choose M here: the + module will be called maple_keyb. + +config KEYBOARD_NEWTON + tristate "Newton keyboard" + select SERIO + help + Say Y here if you have a Newton keyboard on a serial port. + + To compile this driver as a module, choose M here: the + module will be called newtonkbd. config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" @@ -288,51 +268,38 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_AAED2000 - tristate "AAED-2000 keyboard" - depends on MACH_AAED2000 - select INPUT_POLLDEV +config KEYBOARD_SPITZ + tristate "Spitz keyboard" + depends on PXA_SHARPSL default y help - Say Y here to enable the keyboard on the Agilent AAED-2000 - development board. - - To compile this driver as a module, choose M here: the - module will be called aaed2000_kbd. - -config KEYBOARD_GPIO - tristate "GPIO Buttons" - depends on GENERIC_GPIO - help - This driver implements support for buttons connected - to GPIO pins of various CPUs (and some other chips). - - Say Y here if your device has buttons connected - directly to such GPIO pins. Your board-specific - setup logic must also provide a platform device, - with configuration data saying which GPIOs are used. + Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, + SL-C3000 and Sl-C3100 series of PDAs. To compile this driver as a module, choose M here: the - module will be called gpio-keys. + module will be called spitzkbd. -config KEYBOARD_MAPLE - tristate "Maple bus keyboard" - depends on SH_DREAMCAST && MAPLE +config KEYBOARD_STOWAWAY + tristate "Stowaway keyboard" + select SERIO help - Say Y here if you have a Dreamcast console running Linux and have - a keyboard attached to its Maple bus. + Say Y here if you have a Stowaway keyboard on a serial port. + Stowaway compatible keyboards like Dicota Input-PDA keyboard + are also supported by this driver. To compile this driver as a module, choose M here: the - module will be called maple_keyb. + module will be called stowaway. -config KEYBOARD_BFIN - tristate "Blackfin BF54x keypad support" - depends on (BF54x && !BF544) +config KEYBOARD_SUNKBD + tristate "Sun Type 4 and Type 5 keyboard" + select SERIO help - Say Y here if you want to use the BF54x keypad. + Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, + connected either to the Sun keyboard connector or to an serial + (RS-232) port via a simple adapter. To compile this driver as a module, choose M here: the - module will be called bf54x-keys. + module will be called sunkbd. config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" @@ -344,13 +311,45 @@ config KEYBOARD_SH_KEYSC To compile this driver as a module, choose M here: the module will be called sh_keysc. -config KEYBOARD_EP93XX - tristate "EP93xx Matrix Keypad support" - depends on ARCH_EP93XX +config KEYBOARD_OMAP + tristate "TI OMAP keypad support" + depends on (ARCH_OMAP1 || ARCH_OMAP2) help - Say Y here to enable the matrix keypad on the Cirrus EP93XX. + Say Y here if you want to use the OMAP keypad. To compile this driver as a module, choose M here: the - module will be called ep93xx_keypad. + module will be called omap-keypad. + +config KEYBOARD_TOSA + tristate "Tosa keyboard" + depends on MACH_TOSA + default y + help + Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) + + To compile this driver as a module, choose M here: the + module will be called tosakbd. + +config KEYBOARD_TOSA_USE_EXT_KEYCODES + bool "Tosa keyboard: use extended keycodes" + depends on KEYBOARD_TOSA + help + Say Y here to enable the tosa keyboard driver to generate extended + (>= 127) keycodes. Be aware, that they can't be correctly interpreted + by either console keyboard driver or by Kdrive keybd driver. + + Say Y only if you know, what you are doing! + +config KEYBOARD_XTKBD + tristate "XT keyboard" + select SERIO + help + Say Y here if you want to use the old IBM PC/XT keyboard (or + compatible) on your system. This is only possible with a + parallel port keyboard adapter, you cannot connect it to the + keyboard port on a PC that runs Linux. + + To compile this driver as a module, choose M here: the + module will be called xtkbd. endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 156b647a259b7..632efbc18c44e 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -4,29 +4,29 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o -obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o -obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o -obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o +obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o -obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o -obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o -obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o +obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o -obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o -obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o +obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o +obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o +obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o +obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o +obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o +obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o +obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o -obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o -obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o -obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o -obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o -obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o -obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o +obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o +obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o -- GitLab From bab7614d6d1b1fc96ec6c5a7ca34c8641060e659 Mon Sep 17 00:00:00 2001 From: Eric Miao <eric.y.miao@gmail.com> Date: Mon, 29 Jun 2009 00:20:52 -0700 Subject: [PATCH 0326/1002] Input: add support for generic GPIO-based matrix keypad Original patch by Marek Vasut, modified by Eric in: 1. use delayed work to simplify the debouncing 2. combine col_polarity/row_polarity into a single active_low field 3. use a generic bit array based XOR algorithm to detect key press/release, which should make the column assertion time shorter and code a bit cleaner 4. remove the ALT_FN handling, which is no way generic, the ALT_FN key should be treated as no different from other keys, and translation will be done by user space by commands like 'loadkeys'. 5. explicitly disable row IRQs and flush potential pending work, and schedule an immediate scan after resuming as suggested by Uli Luckas 6. incorporate review comments from many others Patch tested on Littleton/PXA310 (though PXA310 has a dedicate keypad controller, I have to configure those pins as generic GPIO to use this driver, works quite well, though), and Sharp Zaurus model SL-C7x0 and SL-C1000. [dtor@mail.ru: fix error unwinding path, support changing keymap from userspace] Signed-off-by: Marek Vasut <marek.vasut@gmail.com> Reviewed-by: Trilok Soni <soni.trilok@gmail.com> Reviewed-by: Uli Luckas <u.luckas@road.de> Reviewed-by: Russell King <linux@arm.linux.org.uk> Reviewed-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Eric Miao <eric.miao@marvell.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/keyboard/Kconfig | 13 +- drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/matrix_keypad.c | 453 +++++++++++++++++++++++++ include/linux/input/matrix_keypad.h | 65 ++++ 4 files changed, 530 insertions(+), 2 deletions(-) create mode 100644 drivers/input/keyboard/matrix_keypad.c create mode 100644 include/linux/input/matrix_keypad.h diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index d2df1030675ab..a6b989a9dc07e 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -158,7 +158,16 @@ config KEYBOARD_GPIO with configuration data saying which GPIOs are used. To compile this driver as a module, choose M here: the - module will be called gpio-keys. + module will be called gpio_keys. + +config KEYBOARD_MATRIX + tristate "GPIO driven matrix keypad support" + depends on GENERIC_GPIO + help + Enable support for GPIO driven matrix keypad. + + To compile this driver as a module, choose M here: the + module will be called matrix_keypad. config KEYBOARD_HIL_OLD tristate "HP HIL keyboard support (simple driver)" @@ -254,7 +263,7 @@ config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" depends on PXA27x || PXA3xx help - Enable support for PXA27x/PXA3xx keypad controller + Enable support for PXA27x/PXA3xx keypad controller. To compile this driver as a module, choose M here: the module will be called pxa27x_keypad. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 632efbc18c44e..b5b5eae9724fa 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o +obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c new file mode 100644 index 0000000000000..e9b2e7cb05be2 --- /dev/null +++ b/drivers/input/keyboard/matrix_keypad.c @@ -0,0 +1,453 @@ +/* + * GPIO driven matrix keyboard driver + * + * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com> + * + * Based on corgikbd.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/input/matrix_keypad.h> + +struct matrix_keypad { + const struct matrix_keypad_platform_data *pdata; + struct input_dev *input_dev; + unsigned short *keycodes; + + uint32_t last_key_state[MATRIX_MAX_COLS]; + struct delayed_work work; + bool scan_pending; + bool stopped; + spinlock_t lock; +}; + +/* + * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause + * minmal side effect when scanning other columns, here it is configured to + * be input, and it should work on most platforms. + */ +static void __activate_col(const struct matrix_keypad_platform_data *pdata, + int col, bool on) +{ + bool level_on = !pdata->active_low; + + if (on) { + gpio_direction_output(pdata->col_gpios[col], level_on); + } else { + gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); + gpio_direction_input(pdata->col_gpios[col]); + } +} + +static void activate_col(const struct matrix_keypad_platform_data *pdata, + int col, bool on) +{ + __activate_col(pdata, col, on); + + if (on && pdata->col_scan_delay_us) + udelay(pdata->col_scan_delay_us); +} + +static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, + bool on) +{ + int col; + + for (col = 0; col < pdata->num_col_gpios; col++) + __activate_col(pdata, col, on); +} + +static bool row_asserted(const struct matrix_keypad_platform_data *pdata, + int row) +{ + return gpio_get_value_cansleep(pdata->row_gpios[row]) ? + !pdata->active_low : pdata->active_low; +} + +static void enable_row_irqs(struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + for (i = 0; i < pdata->num_row_gpios; i++) + enable_irq(gpio_to_irq(pdata->row_gpios[i])); +} + +static void disable_row_irqs(struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + for (i = 0; i < pdata->num_row_gpios; i++) + disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); +} + +/* + * This gets the keys from keyboard and reports it to input subsystem + */ +static void matrix_keypad_scan(struct work_struct *work) +{ + struct matrix_keypad *keypad = + container_of(work, struct matrix_keypad, work.work); + struct input_dev *input_dev = keypad->input_dev; + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + uint32_t new_state[MATRIX_MAX_COLS]; + int row, col, code; + + /* de-activate all columns for scanning */ + activate_all_cols(pdata, false); + + memset(new_state, 0, sizeof(new_state)); + + /* assert each column and read the row status out */ + for (col = 0; col < pdata->num_col_gpios; col++) { + + activate_col(pdata, col, true); + + for (row = 0; row < pdata->num_row_gpios; row++) + new_state[col] |= + row_asserted(pdata, row) ? (1 << row) : 0; + + activate_col(pdata, col, false); + } + + for (col = 0; col < pdata->num_col_gpios; col++) { + uint32_t bits_changed; + + bits_changed = keypad->last_key_state[col] ^ new_state[col]; + if (bits_changed == 0) + continue; + + for (row = 0; row < pdata->num_row_gpios; row++) { + if ((bits_changed & (1 << row)) == 0) + continue; + + code = (row << 4) + col; + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, + keypad->keycodes[code], + new_state[col] & (1 << row)); + } + } + input_sync(input_dev); + + memcpy(keypad->last_key_state, new_state, sizeof(new_state)); + + activate_all_cols(pdata, true); + + /* Enable IRQs again */ + spin_lock_irq(&keypad->lock); + keypad->scan_pending = false; + enable_row_irqs(keypad); + spin_unlock_irq(&keypad->lock); +} + +static irqreturn_t matrix_keypad_interrupt(int irq, void *id) +{ + struct matrix_keypad *keypad = id; + unsigned long flags; + + spin_lock_irqsave(&keypad->lock, flags); + + /* + * See if another IRQ beaten us to it and scheduled the + * scan already. In that case we should not try to + * disable IRQs again. + */ + if (unlikely(keypad->scan_pending || keypad->stopped)) + goto out; + + disable_row_irqs(keypad); + keypad->scan_pending = true; + schedule_delayed_work(&keypad->work, + msecs_to_jiffies(keypad->pdata->debounce_ms)); + +out: + spin_unlock_irqrestore(&keypad->lock, flags); + return IRQ_HANDLED; +} + +static int matrix_keypad_start(struct input_dev *dev) +{ + struct matrix_keypad *keypad = input_get_drvdata(dev); + + keypad->stopped = false; + mb(); + + /* + * Schedule an immediate key scan to capture current key state; + * columns will be activated and IRQs be enabled after the scan. + */ + schedule_delayed_work(&keypad->work, 0); + + return 0; +} + +static void matrix_keypad_stop(struct input_dev *dev) +{ + struct matrix_keypad *keypad = input_get_drvdata(dev); + + keypad->stopped = true; + mb(); + flush_work(&keypad->work.work); + /* + * matrix_keypad_scan() will leave IRQs enabled; + * we should disable them now. + */ + disable_row_irqs(keypad); +} + +#ifdef CONFIG_PM +static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + matrix_keypad_stop(keypad->input_dev); + + if (device_may_wakeup(&pdev->dev)) + for (i = 0; i < pdata->num_row_gpios; i++) + enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + + return 0; +} + +static int matrix_keypad_resume(struct platform_device *pdev) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + if (device_may_wakeup(&pdev->dev)) + for (i = 0; i < pdata->num_row_gpios; i++) + disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + + matrix_keypad_start(keypad->input_dev); + + return 0; +} +#else +#define matrix_keypad_suspend NULL +#define matrix_keypad_resume NULL +#endif + +static int __devinit init_matrix_gpio(struct platform_device *pdev, + struct matrix_keypad *keypad) +{ + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i, err = -EINVAL; + + /* initialized strobe lines as outputs, activated */ + for (i = 0; i < pdata->num_col_gpios; i++) { + err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for COL%d\n", + pdata->col_gpios[i], i); + goto err_free_cols; + } + + gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); + } + + for (i = 0; i < pdata->num_row_gpios; i++) { + err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for ROW%d\n", + pdata->row_gpios[i], i); + goto err_free_rows; + } + + gpio_direction_input(pdata->row_gpios[i]); + } + + for (i = 0; i < pdata->num_row_gpios; i++) { + err = request_irq(gpio_to_irq(pdata->row_gpios[i]), + matrix_keypad_interrupt, + IRQF_DISABLED | + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "matrix-keypad", keypad); + if (err) { + dev_err(&pdev->dev, + "Unable to acquire interrupt for GPIO line %i\n", + pdata->row_gpios[i]); + goto err_free_irqs; + } + } + + /* initialized as disabled - enabled by input->open */ + disable_row_irqs(keypad); + return 0; + +err_free_irqs: + while (--i >= 0) + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); + i = pdata->num_row_gpios; +err_free_rows: + while (--i >= 0) + gpio_free(pdata->row_gpios[i]); + i = pdata->num_col_gpios; +err_free_cols: + while (--i >= 0) + gpio_free(pdata->col_gpios[i]); + + return err; +} + +static int __devinit matrix_keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keypad_platform_data *pdata; + const struct matrix_keymap_data *keymap_data; + struct matrix_keypad *keypad; + struct input_dev *input_dev; + unsigned short *keycodes; + int i; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } + + keymap_data = pdata->keymap_data; + if (!keymap_data) { + dev_err(&pdev->dev, "no keymap data defined\n"); + return -EINVAL; + } + + if (!keymap_data->max_keymap_size) { + dev_err(&pdev->dev, "invalid keymap data supplied\n"); + return -EINVAL; + } + + keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); + keycodes = kzalloc(keymap_data->max_keymap_size * + sizeof(keypad->keycodes), + GFP_KERNEL); + input_dev = input_allocate_device(); + if (!keypad || !keycodes || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } + + keypad->input_dev = input_dev; + keypad->pdata = pdata; + keypad->keycodes = keycodes; + keypad->stopped = true; + INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); + spin_lock_init(&keypad->lock); + + input_dev->name = pdev->name; + input_dev->id.bustype = BUS_HOST; + input_dev->dev.parent = &pdev->dev; + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_dev->open = matrix_keypad_start; + input_dev->close = matrix_keypad_stop; + + input_dev->keycode = keycodes; + input_dev->keycodesize = sizeof(*keycodes); + input_dev->keycodemax = keymap_data->max_keymap_size; + + for (i = 0; i < keymap_data->keymap_size; i++) { + unsigned int key = keymap_data->keymap[i]; + unsigned int row = KEY_ROW(key); + unsigned int col = KEY_COL(key); + unsigned short code = KEY_VAL(key); + + keycodes[(row << 4) + col] = code; + __set_bit(code, input_dev->keybit); + } + __clear_bit(KEY_RESERVED, input_dev->keybit); + + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, keypad); + + err = init_matrix_gpio(pdev, keypad); + if (err) + goto err_free_mem; + + err = input_register_device(keypad->input_dev); + if (err) + goto err_free_mem; + + device_init_wakeup(&pdev->dev, pdata->wakeup); + platform_set_drvdata(pdev, keypad); + + return 0; + +err_free_mem: + input_free_device(input_dev); + kfree(keycodes); + kfree(keypad); + return err; +} + +static int __devexit matrix_keypad_remove(struct platform_device *pdev) +{ + struct matrix_keypad *keypad = platform_get_drvdata(pdev); + const struct matrix_keypad_platform_data *pdata = keypad->pdata; + int i; + + device_init_wakeup(&pdev->dev, 0); + + for (i = 0; i < pdata->num_row_gpios; i++) { + free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); + gpio_free(pdata->row_gpios[i]); + } + + for (i = 0; i < pdata->num_col_gpios; i++) + gpio_free(pdata->col_gpios[i]); + + input_unregister_device(keypad->input_dev); + platform_set_drvdata(pdev, NULL); + kfree(keypad->keycodes); + kfree(keypad); + + return 0; +} + +static struct platform_driver matrix_keypad_driver = { + .probe = matrix_keypad_probe, + .remove = __devexit_p(matrix_keypad_remove), + .suspend = matrix_keypad_suspend, + .resume = matrix_keypad_resume, + .driver = { + .name = "matrix-keypad", + .owner = THIS_MODULE, + }, +}; + +static int __init matrix_keypad_init(void) +{ + return platform_driver_register(&matrix_keypad_driver); +} + +static void __exit matrix_keypad_exit(void) +{ + platform_driver_unregister(&matrix_keypad_driver); +} + +module_init(matrix_keypad_init); +module_exit(matrix_keypad_exit); + +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); +MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:matrix-keypad"); diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h new file mode 100644 index 0000000000000..7964516c69544 --- /dev/null +++ b/include/linux/input/matrix_keypad.h @@ -0,0 +1,65 @@ +#ifndef _MATRIX_KEYPAD_H +#define _MATRIX_KEYPAD_H + +#include <linux/types.h> +#include <linux/input.h> + +#define MATRIX_MAX_ROWS 16 +#define MATRIX_MAX_COLS 16 + +#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\ + (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\ + (val & 0xffff)) + +#define KEY_ROW(k) (((k) >> 24) & 0xff) +#define KEY_COL(k) (((k) >> 16) & 0xff) +#define KEY_VAL(k) ((k) & 0xffff) + +/** + * struct matrix_keymap_data - keymap for matrix keyboards + * @keymap: pointer to array of uint32 values encoded with KEY() macro + * representing keymap + * @keymap_size: number of entries (initialized) in this keymap + * @max_keymap_size: maximum size of keymap supported by the device + * + * This structure is supposed to be used by platform code to supply + * keymaps to drivers that implement matrix-like keypads/keyboards. + */ +struct matrix_keymap_data { + const uint32_t *keymap; + unsigned int keymap_size; + unsigned int max_keymap_size; +}; + +/** + * struct matrix_keypad_platform_data - platform-dependent keypad data + * @keymap_data: pointer to &matrix_keymap_data + * @row_gpios: array of gpio numbers reporesenting rows + * @col_gpios: array of gpio numbers reporesenting colums + * @num_row_gpios: actual number of row gpios used by device + * @num_col_gpios: actual number of col gpios used by device + * @col_scan_delay_us: delay, measured in microseconds, that is + * needed before we can keypad after activating column gpio + * @debounce_ms: debounce interval in milliseconds + * + * This structure represents platform-specific data that use used by + * matrix_keypad driver to perform proper initialization. + */ +struct matrix_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; + + unsigned int row_gpios[MATRIX_MAX_ROWS]; + unsigned int col_gpios[MATRIX_MAX_COLS]; + unsigned int num_row_gpios; + unsigned int num_col_gpios; + + unsigned int col_scan_delay_us; + + /* key debounce interval in milli-second */ + unsigned int debounce_ms; + + bool active_low; + bool wakeup; +}; + +#endif /* _MATRIX_KEYPAD_H */ -- GitLab From 9a660a6e1a0ebef72cf792583777234483a40022 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 16:26:13 +0000 Subject: [PATCH 0327/1002] arch/sh/boards/mach-se/7206/io.c: Remove unnecessary semicolons Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/boards/mach-se/7206/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/boards/mach-se/7206/io.c b/arch/sh/boards/mach-se/7206/io.c index 9c3a33210d617..180455642a432 100644 --- a/arch/sh/boards/mach-se/7206/io.c +++ b/arch/sh/boards/mach-se/7206/io.c @@ -50,7 +50,7 @@ unsigned char se7206_inb_p(unsigned long port) unsigned short se7206_inw(unsigned long port) { - return *port2adr(port);; + return *port2adr(port); } void se7206_outb(unsigned char value, unsigned long port) -- GitLab From ec87805c63a96e8863385d79c864801a572a4ab8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <morimoto.kuninori@renesas.com> Date: Mon, 29 Jun 2009 07:40:00 +0000 Subject: [PATCH 0328/1002] sh: ms7724se: Enable sh_eth in defconfig. Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/configs/se7724_defconfig | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig index 3840270283e44..3ee783a0a075c 100644 --- a/arch/sh/configs/se7724_defconfig +++ b/arch/sh/configs/se7724_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.30 -# Thu Jun 18 16:09:05 2009 +# Mon Jun 29 16:28:43 2009 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -14,6 +14,7 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -28,7 +29,9 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y # # General setup @@ -88,10 +91,12 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y +CONFIG_HAVE_PERF_COUNTERS=y # # Performance Counters # +# CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y # CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y @@ -107,6 +112,10 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -119,7 +128,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y -# CONFIG_LBD is not set +CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -584,7 +593,6 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set -# CONFIG_SCSI_BNX2_ISCSI is not set # CONFIG_LIBFC is not set # CONFIG_LIBFCOE is not set # CONFIG_SCSI_DEBUG is not set @@ -624,7 +632,7 @@ CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set # CONFIG_STNIC is not set -# CONFIG_SH_ETH is not set +CONFIG_SH_ETH=y CONFIG_SMC91X=y # CONFIG_ENC28J60 is not set # CONFIG_ETHOC is not set @@ -801,6 +809,11 @@ CONFIG_SPI_BITBANG=y # # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_GPIO_SYSFS is not set @@ -851,6 +864,8 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1196,6 +1211,7 @@ CONFIG_RTC_DRV_PCF8563=y # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set # # SPI RTC drivers @@ -1260,6 +1276,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set CONFIG_FILE_LOCKING=y -- GitLab From 4078c444cf667f018c3fc7ebf141131a2b7c9480 Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Mon, 29 Jun 2009 00:41:11 -0700 Subject: [PATCH 0329/1002] perf_counter, x86: Update x86_pmu after WARN() The print out should read the value before changing the value. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <4A487017.4090007@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/cpu/perf_counter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index b83474b6021ad..d4cf4ce19aac5 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -1496,17 +1496,17 @@ void __init init_hw_perf_counters(void) pr_cont("%s PMU driver.\n", x86_pmu.name); if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { - x86_pmu.num_counters = X86_PMC_MAX_GENERIC; WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!", x86_pmu.num_counters, X86_PMC_MAX_GENERIC); + x86_pmu.num_counters = X86_PMC_MAX_GENERIC; } perf_counter_mask = (1 << x86_pmu.num_counters) - 1; perf_max_counters = x86_pmu.num_counters; if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) { - x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED; WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!", x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED); + x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED; } perf_counter_mask |= -- GitLab From 238a24f626628cb16a3015f332d649f08246ca89 Mon Sep 17 00:00:00 2001 From: Li Zefan <lizf@cn.fujitsu.com> Date: Mon, 29 Jun 2009 15:55:10 +0800 Subject: [PATCH 0330/1002] tracing/fastboot: Document the need of initcall_debug To use boot tracer, one should pass initcall_debug as well as ftrace=initcall to the command line. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <4A48735E.9050002@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 1551f47e7669b..019f380fd764c 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -226,13 +226,13 @@ config BOOT_TRACER the timings of the initcalls and traces key events and the identity of tasks that can cause boot delays, such as context-switches. - Its aim is to be parsed by the /scripts/bootgraph.pl tool to + Its aim is to be parsed by the scripts/bootgraph.pl tool to produce pretty graphics about boot inefficiencies, giving a visual representation of the delays during initcalls - but the raw /debug/tracing/trace text output is readable too. - You must pass in ftrace=initcall to the kernel command line - to enable this on bootup. + You must pass in initcall_debug and ftrace=initcall to the kernel + command line to enable this on bootup. config TRACE_BRANCH_PROFILING bool -- GitLab From 1d955ebd4db7961dc4e772a23288b3d5c6f191be Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Mon, 29 Jun 2009 11:33:53 +0200 Subject: [PATCH 0331/1002] ALSA: hda - Add missing initializations for ALC268 and ALC269 During the changes to clean up / fix the realtek codec initialization routines in commit 4a79ba34cada6a5a4ee86ed53aa8a73ba1e6fc51, I forgot to add the check for ALC268 and ALC269. This resulted in the missing EAPD and COEF setup for these codecs. This patch adds the missing checks for these codecs. Reference: bko#13633 http://bugzilla.kernel.org/show_bug.cgi?id=13633 Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 08846d222cbe1..3a8e58c483dfd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12463,6 +12463,8 @@ static int alc268_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; + alc_ssid_check(codec, 0x15, 0x1b, 0x14); + return 1; } @@ -13371,6 +13373,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) if (!spec->cap_mixer && !spec->no_analog) set_capture_mixer(spec); + alc_ssid_check(codec, 0x15, 0x1b, 0x14); + return 1; } -- GitLab From 59c5fe6d848cae8fd51498d17532f5aad3866f98 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Mon, 29 Jun 2009 12:11:50 +0100 Subject: [PATCH 0332/1002] [ARM] 5562/2: at91: add gpio button support for at91sam9g20ek This adds input keyboard gpio support on at91sam9g20ek board. It adds button 3 and 4. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-sam9g20ek.c | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index cc270beadd5d6..a55398ed1211d 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -24,6 +24,8 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/spi/at73c213.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> #include <linux/clk.h> #include <mach/hardware.h> @@ -218,6 +220,56 @@ static struct gpio_led ek_leds[] = { } }; + +/* + * GPIO Buttons + */ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button ek_buttons[] = { + { + .gpio = AT91_PIN_PA30, + .code = BTN_3, + .desc = "Button 3", + .active_low = 1, + .wakeup = 1, + }, + { + .gpio = AT91_PIN_PA31, + .code = BTN_4, + .desc = "Button 4", + .active_low = 1, + .wakeup = 1, + } +}; + +static struct gpio_keys_platform_data ek_button_data = { + .buttons = ek_buttons, + .nbuttons = ARRAY_SIZE(ek_buttons), +}; + +static struct platform_device ek_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &ek_button_data, + } +}; + +static void __init ek_add_device_buttons(void) +{ + at91_set_gpio_input(AT91_PIN_PA30, 1); /* btn3 */ + at91_set_deglitch(AT91_PIN_PA30, 1); + at91_set_gpio_input(AT91_PIN_PA31, 1); /* btn4 */ + at91_set_deglitch(AT91_PIN_PA31, 1); + + platform_device_register(&ek_button_device); +} +#else +static void __init ek_add_device_buttons(void) {} +#endif + + static struct i2c_board_info __initdata ek_i2c_devices[] = { { I2C_BOARD_INFO("24c512", 0x50), @@ -245,6 +297,8 @@ static void __init ek_board_init(void) at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* LEDs */ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); + /* Push Buttons */ + ek_add_device_buttons(); /* PCK0 provides MCLK to the WM8731 */ at91_set_B_periph(AT91_PIN_PC1, 0); /* SSC (for WM8731) */ -- GitLab From bf92df30df909710c498d05620e2df1be1ef779b Mon Sep 17 00:00:00 2001 From: Yu Zhao <yu.zhao@intel.com> Date: Mon, 29 Jun 2009 11:31:45 +0800 Subject: [PATCH 0333/1002] intel-iommu: Only avoid flushing device IOTLB for domain ID 0 in caching mode In caching mode, domain ID 0 is reserved for non-present to present mapping flush. Device IOTLB doesn't need to be flushed in this case. Previously we were avoiding the flush for domain zero, even if the IOMMU wasn't in caching mode and domain zero wasn't special. Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 420afa8872837..3cad7006ed8eb 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1054,7 +1054,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, else iommu->flush.flush_iotlb(iommu, did, addr, mask, DMA_TLB_PSI_FLUSH); - if (did) + + /* + * In caching mode, domain ID 0 is reserved for non-present to present + * mapping flush. Device IOTLB doesn't need to be flushed in this case. + */ + if (!cap_caching_mode(iommu->cap) || did) iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); } -- GitLab From b213203e475212a69ad6fedfb73464087e317148 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Fri, 26 Jun 2009 18:50:28 +0100 Subject: [PATCH 0334/1002] intel-iommu: Create new iommu_domain_identity_map() function We'll want to do this to a _domain_ (the si_domain) rather than a PCI device. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 62 +++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3cad7006ed8eb..3a4f347e2f882 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1849,25 +1849,12 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) static int iommu_identity_mapping; -static int iommu_prepare_identity_map(struct pci_dev *pdev, - unsigned long long start, - unsigned long long end) +static int iommu_domain_identity_map(struct dmar_domain *domain, + unsigned long long start, + unsigned long long end) { - struct dmar_domain *domain; unsigned long size; unsigned long long base; - int ret; - - printk(KERN_INFO - "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", - pci_name(pdev), start, end); - if (iommu_identity_mapping) - domain = si_domain; - else - /* page table init */ - domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); - if (!domain) - return -ENOMEM; /* The address might not be aligned */ base = start & PAGE_MASK; @@ -1876,31 +1863,54 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, if (!reserve_iova(&domain->iovad, IOVA_PFN(base), IOVA_PFN(base + size) - 1)) { printk(KERN_ERR "IOMMU: reserve iova failed\n"); - ret = -ENOMEM; - goto error; + return -ENOMEM; } - pr_debug("Mapping reserved region %lx@%llx for %s\n", - size, base, pci_name(pdev)); + pr_debug("Mapping reserved region %lx@%llx for domain %d\n", + size, base, domain->id); /* * RMRR range might have overlap with physical memory range, * clear it first */ dma_pte_clear_range(domain, base, base + size); - ret = domain_page_mapping(domain, base, base, size, - DMA_PTE_READ|DMA_PTE_WRITE); + return domain_page_mapping(domain, base, base, size, + DMA_PTE_READ|DMA_PTE_WRITE); +} + +static int iommu_prepare_identity_map(struct pci_dev *pdev, + unsigned long long start, + unsigned long long end) +{ + struct dmar_domain *domain; + int ret; + + printk(KERN_INFO + "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", + pci_name(pdev), start, end); + + if (iommu_identity_mapping) + domain = si_domain; + else + /* page table init */ + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); + if (!domain) + return -ENOMEM; + + ret = iommu_domain_identity_map(domain, start, end); if (ret) goto error; /* context entry init */ ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL); - if (!ret) - return 0; -error: + if (ret) + goto error; + + return 0; + + error: domain_exit(domain); return ret; - } static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, -- GitLab From c7ab48d2acaf959e4d59c3f55d12fdb7ca9afd7c Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Fri, 26 Jun 2009 19:10:36 +0100 Subject: [PATCH 0335/1002] intel-iommu: Clean up identity mapping code, remove CONFIG_DMAR_GFX_WA There's no need for the GFX workaround now we have 'iommu=pt' for the cases where people really care about performance. There's no need to have a special case for just one type of device. This also speeds up the iommu=pt path and reduces memory usage by setting up the si_domain _once_ and then using it for all devices, rather than giving each device its own private page tables. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- arch/x86/Kconfig | 15 +----- drivers/pci/intel-iommu.c | 107 ++++++++++++-------------------------- 2 files changed, 34 insertions(+), 88 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d1430ef6b4f9a..c07f722059094 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1913,25 +1913,14 @@ config DMAR_DEFAULT_ON recommended you say N here while the DMAR code remains experimental. -config DMAR_GFX_WA - def_bool y - prompt "Support for Graphics workaround" - depends on DMAR - ---help--- - Current Graphics drivers tend to use physical address - for DMA and avoid using DMA APIs. Setting this config - option permits the IOMMU driver to set a unity map for - all the OS-visible memory. Hence the driver can continue - to use physical addresses for DMA. - config DMAR_FLOPPY_WA def_bool y depends on DMAR ---help--- - Floppy disk drivers are know to bypass DMA API calls + Floppy disk drivers are known to bypass DMA API calls thereby failing to work when IOMMU is enabled. This workaround will setup a 1:1 mapping for the first - 16M to make floppy (an ISA device) work. + 16MiB to make floppy (an ISA device) work. config INTR_REMAP bool "Support for Interrupt Remapping (EXPERIMENTAL)" diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3a4f347e2f882..fc121967cb5b8 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1889,11 +1889,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", pci_name(pdev), start, end); - if (iommu_identity_mapping) - domain = si_domain; - else - /* page table init */ - domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); if (!domain) return -ENOMEM; @@ -1922,64 +1918,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, rmrr->end_address + 1); } -struct iommu_prepare_data { - struct pci_dev *pdev; - int ret; -}; - -static int __init iommu_prepare_work_fn(unsigned long start_pfn, - unsigned long end_pfn, void *datax) -{ - struct iommu_prepare_data *data; - - data = (struct iommu_prepare_data *)datax; - - data->ret = iommu_prepare_identity_map(data->pdev, - start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); - return data->ret; - -} - -static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev) -{ - int nid; - struct iommu_prepare_data data; - - data.pdev = pdev; - data.ret = 0; - - for_each_online_node(nid) { - work_with_active_regions(nid, iommu_prepare_work_fn, &data); - if (data.ret) - return data.ret; - } - return data.ret; -} - -#ifdef CONFIG_DMAR_GFX_WA -static void __init iommu_prepare_gfx_mapping(void) -{ - struct pci_dev *pdev = NULL; - int ret; - - for_each_pci_dev(pdev) { - if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || - !IS_GFX_DEVICE(pdev)) - continue; - printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", - pci_name(pdev)); - ret = iommu_prepare_with_active_regions(pdev); - if (ret) - printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); - } -} -#else /* !CONFIG_DMAR_GFX_WA */ -static inline void iommu_prepare_gfx_mapping(void) -{ - return; -} -#endif - #ifdef CONFIG_DMAR_FLOPPY_WA static inline void iommu_prepare_isa(void) { @@ -1990,12 +1928,12 @@ static inline void iommu_prepare_isa(void) if (!pdev) return; - printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); + printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); if (ret) - printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " - "floppy might not work\n"); + printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " + "floppy might not work\n"); } #else @@ -2023,16 +1961,30 @@ static int __init init_context_pass_through(void) } static int md_domain_init(struct dmar_domain *domain, int guest_width); + +static int __init si_domain_work_fn(unsigned long start_pfn, + unsigned long end_pfn, void *datax) +{ + int *ret = datax; + + *ret = iommu_domain_identity_map(si_domain, + (uint64_t)start_pfn << PAGE_SHIFT, + (uint64_t)end_pfn << PAGE_SHIFT); + return *ret; + +} + static int si_domain_init(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; - int ret = 0; + int nid, ret = 0; si_domain = alloc_domain(); if (!si_domain) return -EFAULT; + pr_debug("Identity mapping domain is domain %d\n", si_domain->id); for_each_active_iommu(iommu, drhd) { ret = iommu_attach_domain(si_domain, iommu); @@ -2049,6 +2001,12 @@ static int si_domain_init(void) si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; + for_each_online_node(nid) { + work_with_active_regions(nid, si_domain_work_fn, &ret); + if (ret) + return ret; + } + return 0; } @@ -2102,13 +2060,14 @@ static int iommu_prepare_static_identity_mapping(void) if (ret) return -EFAULT; - printk(KERN_INFO "IOMMU: Setting identity map:\n"); for_each_pci_dev(pdev) { - ret = iommu_prepare_with_active_regions(pdev); - if (ret) { - printk(KERN_INFO "1:1 mapping to one domain failed.\n"); - return -EFAULT; - } + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", + pci_name(pdev)); + + ret = domain_context_mapping(si_domain, pdev, + CONTEXT_TT_MULTI_LEVEL); + if (ret) + return ret; ret = domain_add_dev_info(si_domain, pdev); if (ret) return ret; @@ -2299,8 +2258,6 @@ int __init init_dmars(void) } } - iommu_prepare_gfx_mapping(); - iommu_prepare_isa(); } -- GitLab From dd4e831960e4f0214480fa96a53ca9bb7dd04927 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 16:21:20 +0100 Subject: [PATCH 0336/1002] intel-iommu: Change dma_set_pte_addr() to dma_set_pte_pfn() Add some helpers for converting between VT-d and normal system pfns, since system pages can be larger than VT-d pages. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fc121967cb5b8..852f40a913d43 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -65,6 +65,26 @@ #define PHYSICAL_PAGE_MASK PAGE_MASK #endif +/* VT-d pages must always be _smaller_ than MM pages. Otherwise things + are never going to work. */ +static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn) +{ + return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT); +} + +static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn) +{ + return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT); +} +static inline unsigned long page_to_dma_pfn(struct page *pg) +{ + return mm_to_dma_pfn(page_to_pfn(pg)); +} +static inline unsigned long virt_to_dma_pfn(void *p) +{ + return page_to_dma_pfn(virt_to_page(p)); +} + /* global iommu list, set NULL for ignored DMAR units */ static struct intel_iommu **g_iommus; @@ -207,9 +227,9 @@ static inline u64 dma_pte_addr(struct dma_pte *pte) return (pte->val & VTD_PAGE_MASK); } -static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr) +static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) { - pte->val |= (addr & VTD_PAGE_MASK); + pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT; } static inline bool dma_pte_present(struct dma_pte *pte) @@ -702,7 +722,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) return NULL; } domain_flush_cache(domain, tmp_page, PAGE_SIZE); - dma_set_pte_addr(pte, virt_to_phys(tmp_page)); + dma_set_pte_pfn(pte, virt_to_dma_pfn(tmp_page)); /* * high level table always sets r/w, last level page * table control read/write @@ -1648,7 +1668,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, * touches the iova range */ BUG_ON(dma_pte_addr(pte)); - dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT); + dma_set_pte_pfn(pte, start_pfn); dma_set_pte_prot(pte, prot); if (prot & DMA_PTE_SNP) dma_set_pte_snp(pte); -- GitLab From 77dfa56c94d2855a25ff552b74980a5538e129f8 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 16:40:08 +0100 Subject: [PATCH 0337/1002] intel-iommu: Change address_level_offset() to pfn_level_offset() We're shifting the inputs for now, but that'll change... Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 852f40a913d43..529c1c13048f3 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -671,9 +671,9 @@ static inline unsigned int level_to_offset_bits(int level) return (12 + (level - 1) * LEVEL_STRIDE); } -static inline int address_level_offset(u64 addr, int level) +static inline int pfn_level_offset(unsigned long pfn, int level) { - return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); + return (pfn >> (level_to_offset_bits(level) - 12)) & LEVEL_MASK; } static inline u64 level_mask(int level) @@ -708,7 +708,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) while (level > 0) { void *tmp_page; - offset = address_level_offset(addr, level); + offset = pfn_level_offset(addr >> VTD_PAGE_SHIFT, level); pte = &parent[offset]; if (level == 1) break; @@ -749,7 +749,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, parent = domain->pgd; while (level <= total) { - offset = address_level_offset(addr, total); + offset = pfn_level_offset(addr >> VTD_PAGE_SHIFT, total); pte = &parent[offset]; if (level == total) return pte; -- GitLab From 90dcfb5eb2fd427b16135a14f176a6902750b6b4 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 17:14:59 +0100 Subject: [PATCH 0338/1002] intel-iommu: Change dma_addr_level_pte() to dma_pfn_level_pte() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 529c1c13048f3..edd39d348a981 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -740,8 +740,9 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) } /* return address's pte at specific level */ -static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, - int level) +static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, + unsigned long pfn, + int level) { struct dma_pte *parent, *pte = NULL; int total = agaw_to_level(domain->agaw); @@ -749,7 +750,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, parent = domain->pgd; while (level <= total) { - offset = pfn_level_offset(addr >> VTD_PAGE_SHIFT, total); + offset = pfn_level_offset(pfn, total); pte = &parent[offset]; if (level == total) return pte; @@ -768,7 +769,7 @@ static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) struct dma_pte *pte = NULL; /* get last level pte */ - pte = dma_addr_level_pte(domain, addr, 1); + pte = dma_pfn_level_pte(domain, addr >> VTD_PAGE_SHIFT, 1); if (pte) { dma_clear_pte(pte); @@ -817,7 +818,8 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, return; while (tmp < end) { - pte = dma_addr_level_pte(domain, tmp, level); + pte = dma_pfn_level_pte(domain, tmp >> VTD_PAGE_SHIFT, + level); if (pte) { free_pgtable_page( phys_to_virt(dma_pte_addr(pte))); -- GitLab From a75f7cf94f01717c5103138319b96752ee2a2be9 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 17:44:39 +0100 Subject: [PATCH 0339/1002] intel-iommu: Make dma_pte_clear_one() take pfn not address Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index edd39d348a981..40eae2097aca2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -764,12 +764,12 @@ static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, } /* clear one page's page table */ -static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) +static void dma_pte_clear_one(struct dmar_domain *domain, unsigned long pfn) { struct dma_pte *pte = NULL; /* get last level pte */ - pte = dma_pfn_level_pte(domain, addr >> VTD_PAGE_SHIFT, 1); + pte = dma_pfn_level_pte(domain, pfn, 1); if (pte) { dma_clear_pte(pte); @@ -792,7 +792,7 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) /* we don't need lock here, nobody else touches the iova range */ while (npages--) { - dma_pte_clear_one(domain, start); + dma_pte_clear_one(domain, start >> VTD_PAGE_SHIFT); start += VTD_PAGE_SIZE; } } -- GitLab From 66eae8469e4e4ba6f4ca7ef82103c78f6d645583 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 19:00:32 +0100 Subject: [PATCH 0340/1002] intel-iommu: Don't just mask out too-big physical addresses; BUG() instead Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 40eae2097aca2..ad367f53a2bba 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -700,8 +700,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) unsigned long flags; BUG_ON(!domain->pgd); - - addr &= (((u64)1) << addr_width) - 1; + BUG_ON(addr >> addr_width); parent = domain->pgd; spin_lock_irqsave(&domain->mapping_lock, flags); @@ -783,8 +782,9 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) int addr_width = agaw_to_width(domain->agaw); int npages; - start &= (((u64)1) << addr_width) - 1; - end &= (((u64)1) << addr_width) - 1; + BUG_ON(start >> addr_width); + BUG_ON((end-1) >> addr_width); + /* in case it's partial page */ start &= PAGE_MASK; end = PAGE_ALIGN(end); @@ -807,8 +807,8 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, int level; u64 tmp; - start &= (((u64)1) << addr_width) - 1; - end &= (((u64)1) << addr_width) - 1; + BUG_ON(start >> addr_width); + BUG_ON(end >> addr_width); /* we don't need lock here, nobody else touches the iova range */ level = 2; @@ -1654,7 +1654,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, int index; int addr_width = agaw_to_width(domain->agaw); - hpa &= (((u64)1) << addr_width) - 1; + BUG_ON(hpa >> addr_width); if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) return -EINVAL; -- GitLab From a3a9f79e361e864f0e9d75ebe2a0cb43d17c4272 Mon Sep 17 00:00:00 2001 From: Patrick McHardy <kaber@trash.net> Date: Mon, 29 Jun 2009 14:07:56 +0200 Subject: [PATCH 0341/1002] netfilter: tcp conntrack: fix unacknowledged data detection with NAT When NAT helpers change the TCP packet size, the highest seen sequence number needs to be corrected. This is currently only done upwards, when the packet size is reduced the sequence number is unchanged. This causes TCP conntrack to falsely detect unacknowledged data and decrease the timeout. Fix by updating the highest seen sequence number in both directions after packet mangling. Tested-by: Krzysztof Piotr Oledzki <ole@ans.pl> Signed-off-by: Patrick McHardy <kaber@trash.net> --- include/net/netfilter/nf_conntrack.h | 4 ++-- net/ipv4/netfilter/nf_nat_helper.c | 17 +++++++++++------ net/netfilter/nf_conntrack_proto_tcp.c | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index a632689b61b40..cbdd6284996d3 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -258,8 +258,8 @@ static inline bool nf_ct_kill(struct nf_conn *ct) /* Update TCP window tracking data when NAT mangles the packet */ extern void nf_conntrack_tcp_update(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conn *ct, - int dir); + struct nf_conn *ct, int dir, + s16 offset); /* Fake conntrack entry for untracked connections */ extern struct nf_conn nf_conntrack_untracked; diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 155c008626c82..09172a65d9b61 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -191,7 +191,8 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, ct, ctinfo); /* Tell TCP window tracking about seq change */ nf_conntrack_tcp_update(skb, ip_hdrlen(skb), - ct, CTINFO2DIR(ctinfo)); + ct, CTINFO2DIR(ctinfo), + (int)rep_len - (int)match_len); nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); } @@ -377,6 +378,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, struct tcphdr *tcph; int dir; __be32 newseq, newack; + s16 seqoff, ackoff; struct nf_conn_nat *nat = nfct_nat(ct); struct nf_nat_seq *this_way, *other_way; @@ -390,15 +392,18 @@ nf_nat_seq_adjust(struct sk_buff *skb, tcph = (void *)skb->data + ip_hdrlen(skb); if (after(ntohl(tcph->seq), this_way->correction_pos)) - newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); + seqoff = this_way->offset_after; else - newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); + seqoff = this_way->offset_before; if (after(ntohl(tcph->ack_seq) - other_way->offset_before, other_way->correction_pos)) - newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); + ackoff = other_way->offset_after; else - newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); + ackoff = other_way->offset_before; + + newseq = htonl(ntohl(tcph->seq) + seqoff); + newack = htonl(ntohl(tcph->ack_seq) - ackoff); inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); @@ -413,7 +418,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) return 0; - nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); + nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); return 1; } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 33fc0a443f3de..97a82ba75376a 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -720,8 +720,8 @@ static bool tcp_in_window(const struct nf_conn *ct, /* Caller must linearize skb at tcp header. */ void nf_conntrack_tcp_update(const struct sk_buff *skb, unsigned int dataoff, - struct nf_conn *ct, - int dir) + struct nf_conn *ct, int dir, + s16 offset) { const struct tcphdr *tcph = (const void *)skb->data + dataoff; const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; @@ -734,7 +734,7 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb, /* * We have to worry for the ack in the reply packet only... */ - if (after(end, ct->proto.tcp.seen[dir].td_end)) + if (ct->proto.tcp.seen[dir].td_end + offset == end) ct->proto.tcp.seen[dir].td_end = end; ct->proto.tcp.last_end = end; spin_unlock_bh(&ct->lock); -- GitLab From 04b18e65dd5a3e544f07f4bcfa8fb52704a1833b Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 19:15:01 +0100 Subject: [PATCH 0342/1002] intel-iommu: Make dma_pte_clear_range() use pfns Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ad367f53a2bba..d4217f7371594 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -779,21 +779,17 @@ static void dma_pte_clear_one(struct dmar_domain *domain, unsigned long pfn) /* clear last level pte, a tlb flush should be followed */ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) { - int addr_width = agaw_to_width(domain->agaw); - int npages; - - BUG_ON(start >> addr_width); - BUG_ON((end-1) >> addr_width); + unsigned long start_pfn = IOVA_PFN(start); + unsigned long end_pfn = IOVA_PFN(end-1); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - /* in case it's partial page */ - start &= PAGE_MASK; - end = PAGE_ALIGN(end); - npages = (end - start) / VTD_PAGE_SIZE; + BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && end_pfn >> addr_width); - /* we don't need lock here, nobody else touches the iova range */ - while (npages--) { - dma_pte_clear_one(domain, start >> VTD_PAGE_SHIFT); - start += VTD_PAGE_SIZE; + /* we don't need lock here; nobody else touches the iova range */ + while (start_pfn <= end_pfn) { + dma_pte_clear_one(domain, start_pfn); + start_pfn++; } } -- GitLab From 595badf5d65d50300319e6178e6df005ea501f70 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 22:09:11 +0100 Subject: [PATCH 0343/1002] intel-iommu: Make dma_pte_clear_range() take pfns as argument Noting that this is now an _inclusive_ range. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index d4217f7371594..ff8b7ce4a013e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -56,6 +56,7 @@ #define MAX_AGAW_WIDTH 64 #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) +#define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) @@ -777,17 +778,17 @@ static void dma_pte_clear_one(struct dmar_domain *domain, unsigned long pfn) } /* clear last level pte, a tlb flush should be followed */ -static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) +static void dma_pte_clear_range(struct dmar_domain *domain, + unsigned long start_pfn, + unsigned long last_pfn) { - unsigned long start_pfn = IOVA_PFN(start); - unsigned long end_pfn = IOVA_PFN(end-1); int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); - BUG_ON(addr_width < BITS_PER_LONG && end_pfn >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); /* we don't need lock here; nobody else touches the iova range */ - while (start_pfn <= end_pfn) { + while (start_pfn <= last_pfn) { dma_pte_clear_one(domain, start_pfn); start_pfn++; } @@ -1424,7 +1425,7 @@ static void domain_exit(struct dmar_domain *domain) end = end & (~PAGE_MASK); /* clear ptes */ - dma_pte_clear_range(domain, 0, end); + dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); /* free page tables */ dma_pte_free_pagetable(domain, 0, end); @@ -1890,7 +1891,8 @@ static int iommu_domain_identity_map(struct dmar_domain *domain, * RMRR range might have overlap with physical memory range, * clear it first */ - dma_pte_clear_range(domain, base, base + size); + dma_pte_clear_range(domain, base >> VTD_PAGE_SHIFT, + (base + size - 1) >> VTD_PAGE_SHIFT); return domain_page_mapping(domain, base, base, size, DMA_PTE_READ|DMA_PTE_WRITE); @@ -2618,7 +2620,8 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, pci_name(pdev), size, (unsigned long long)start_addr); /* clear the whole page */ - dma_pte_clear_range(domain, start_addr, start_addr + size); + dma_pte_clear_range(domain, start_addr >> VTD_PAGE_SHIFT, + (start_addr + size - 1) >> VTD_PAGE_SHIFT); /* free page tables */ dma_pte_free_pagetable(domain, start_addr, start_addr + size); if (intel_iommu_strict) { @@ -2710,7 +2713,8 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, start_addr = iova->pfn_lo << PAGE_SHIFT; /* clear the whole page */ - dma_pte_clear_range(domain, start_addr, start_addr + size); + dma_pte_clear_range(domain, start_addr >> VTD_PAGE_SHIFT, + (start_addr + size - 1) >> VTD_PAGE_SHIFT); /* free page tables */ dma_pte_free_pagetable(domain, start_addr, start_addr + size); @@ -2792,8 +2796,9 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne size, prot); if (ret) { /* clear the page */ - dma_pte_clear_range(domain, start_addr, - start_addr + offset); + dma_pte_clear_range(domain, + start_addr >> VTD_PAGE_SHIFT, + (start_addr + offset - 1) >> VTD_PAGE_SHIFT); /* free page tables */ dma_pte_free_pagetable(domain, start_addr, start_addr + offset); @@ -3382,7 +3387,7 @@ static void vm_domain_exit(struct dmar_domain *domain) end = end & (~VTD_PAGE_MASK); /* clear ptes */ - dma_pte_clear_range(domain, 0, end); + dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); /* free page tables */ dma_pte_free_pagetable(domain, 0, end); @@ -3526,7 +3531,8 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, /* The address might not be aligned */ base = iova & VTD_PAGE_MASK; size = VTD_PAGE_ALIGN(size); - dma_pte_clear_range(dmar_domain, base, base + size); + dma_pte_clear_range(dmar_domain, base >> VTD_PAGE_SHIFT, + (base + size - 1) >> VTD_PAGE_SHIFT); if (dmar_domain->max_addr == base + size) dmar_domain->max_addr = base; -- GitLab From 8a3af79361e85db6fec4173ef1916322471c19e3 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Date: Mon, 29 Jun 2009 14:28:27 +0200 Subject: [PATCH 0344/1002] netfilter: headers_check fix: linux/netfilter/xt_osf.h fix the following 'make headers_check' warnings: usr/include/linux/netfilter/xt_osf.h:40: found __[us]{8,16,32,64} type without #include <linux/types.h> Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net> --- include/linux/netfilter/xt_osf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/netfilter/xt_osf.h b/include/linux/netfilter/xt_osf.h index fd2272e0959a4..18afa495f9737 100644 --- a/include/linux/netfilter/xt_osf.h +++ b/include/linux/netfilter/xt_osf.h @@ -20,6 +20,8 @@ #ifndef _XT_OSF_H #define _XT_OSF_H +#include <linux/types.h> + #define MAXGENRELEN 32 #define XT_OSF_GENRE (1<<0) -- GitLab From 6660c63a79a639b86e3a709e25a8c4fc3ab24770 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 27 Jun 2009 22:41:00 +0100 Subject: [PATCH 0345/1002] intel-iommu: Make dma_pte_free_pagetable() use pfns Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ff8b7ce4a013e..1526864a9d6fc 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -669,27 +669,27 @@ static inline int width_to_agaw(int width) static inline unsigned int level_to_offset_bits(int level) { - return (12 + (level - 1) * LEVEL_STRIDE); + return (level - 1) * LEVEL_STRIDE; } static inline int pfn_level_offset(unsigned long pfn, int level) { - return (pfn >> (level_to_offset_bits(level) - 12)) & LEVEL_MASK; + return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; } -static inline u64 level_mask(int level) +static inline unsigned long level_mask(int level) { - return ((u64)-1 << level_to_offset_bits(level)); + return -1UL << level_to_offset_bits(level); } -static inline u64 level_size(int level) +static inline unsigned long level_size(int level) { - return ((u64)1 << level_to_offset_bits(level)); + return 1UL << level_to_offset_bits(level); } -static inline u64 align_to_level(u64 addr, int level) +static inline unsigned long align_to_level(unsigned long pfn, int level) { - return ((addr + level_size(level) - 1) & level_mask(level)); + return (pfn + level_size(level) - 1) & level_mask(level); } static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) @@ -798,25 +798,29 @@ static void dma_pte_clear_range(struct dmar_domain *domain, static void dma_pte_free_pagetable(struct dmar_domain *domain, u64 start, u64 end) { - int addr_width = agaw_to_width(domain->agaw); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; + unsigned long start_pfn = start >> VTD_PAGE_SHIFT; + unsigned long last_pfn = (end-1) >> VTD_PAGE_SHIFT; struct dma_pte *pte; int total = agaw_to_level(domain->agaw); int level; - u64 tmp; + unsigned long tmp; - BUG_ON(start >> addr_width); - BUG_ON(end >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); /* we don't need lock here, nobody else touches the iova range */ level = 2; while (level <= total) { - tmp = align_to_level(start, level); - if (tmp >= end || (tmp + level_size(level) > end)) + tmp = align_to_level(start_pfn, level); + + /* Only clear this pte/pmd if we're asked to clear its + _whole_ range */ + if (tmp + level_size(level) - 1 > last_pfn) return; - while (tmp < end) { - pte = dma_pfn_level_pte(domain, tmp >> VTD_PAGE_SHIFT, - level); + while (tmp <= last_pfn) { + pte = dma_pfn_level_pte(domain, tmp, level); if (pte) { free_pgtable_page( phys_to_virt(dma_pte_addr(pte))); @@ -828,7 +832,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, level++; } /* free pgd */ - if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { + if (start == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { free_pgtable_page(domain->pgd); domain->pgd = NULL; } -- GitLab From d794dc9b302c2781c571c10dedb8094e223d31b8 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 00:27:49 +0100 Subject: [PATCH 0346/1002] intel-iommu: Make dma_pte_free_pagetable() take pfns as argument With some cleanup of intel_unmap_page(), intel_unmap_sg() and vm_domain_exit() to no longer play with 64-bit addresses. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 68 ++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1526864a9d6fc..fc593adb049a7 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -796,11 +796,10 @@ static void dma_pte_clear_range(struct dmar_domain *domain, /* free page table pages. last level pte should already be cleared */ static void dma_pte_free_pagetable(struct dmar_domain *domain, - u64 start, u64 end) + unsigned long start_pfn, + unsigned long last_pfn) { int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - unsigned long start_pfn = start >> VTD_PAGE_SHIFT; - unsigned long last_pfn = (end-1) >> VTD_PAGE_SHIFT; struct dma_pte *pte; int total = agaw_to_level(domain->agaw); int level; @@ -832,7 +831,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, level++; } /* free pgd */ - if (start == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { + if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { free_pgtable_page(domain->pgd); domain->pgd = NULL; } @@ -1416,7 +1415,6 @@ static void domain_exit(struct dmar_domain *domain) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; - u64 end; /* Domain 0 is reserved, so dont process it */ if (!domain) @@ -1425,14 +1423,12 @@ static void domain_exit(struct dmar_domain *domain) domain_remove_dev_info(domain); /* destroy iovas */ put_iova_domain(&domain->iovad); - end = DOMAIN_MAX_ADDR(domain->gaw); - end = end & (~PAGE_MASK); /* clear ptes */ dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); /* free page tables */ - dma_pte_free_pagetable(domain, 0, end); + dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); for_each_active_iommu(iommu, drhd) if (test_bit(iommu->seq_id, &domain->iommu_bmp)) @@ -2601,7 +2597,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, { struct pci_dev *pdev = to_pci_dev(dev); struct dmar_domain *domain; - unsigned long start_addr; + unsigned long start_pfn, last_pfn; struct iova *iova; struct intel_iommu *iommu; @@ -2617,20 +2613,22 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, if (!iova) return; - start_addr = iova->pfn_lo << PAGE_SHIFT; - size = aligned_size((u64)dev_addr, size); + start_pfn = mm_to_dma_pfn(iova->pfn_lo); + last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; - pr_debug("Device %s unmapping: %zx@%llx\n", - pci_name(pdev), size, (unsigned long long)start_addr); + pr_debug("Device %s unmapping: pfn %lx-%lx\n", + pci_name(pdev), start_pfn, last_pfn); /* clear the whole page */ - dma_pte_clear_range(domain, start_addr >> VTD_PAGE_SHIFT, - (start_addr + size - 1) >> VTD_PAGE_SHIFT); + dma_pte_clear_range(domain, start_pfn, last_pfn); + /* free page tables */ - dma_pte_free_pagetable(domain, start_addr, start_addr + size); + dma_pte_free_pagetable(domain, start_pfn, last_pfn); + if (intel_iommu_strict) { - iommu_flush_iotlb_psi(iommu, domain->id, start_addr, - size >> VTD_PAGE_SHIFT); + iommu_flush_iotlb_psi(iommu, domain->id, + start_pfn << VTD_PAGE_SHIFT, + last_pfn - start_pfn + 1); /* free iova */ __free_iova(&domain->iovad, iova); } else { @@ -2688,14 +2686,10 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, enum dma_data_direction dir, struct dma_attrs *attrs) { - int i; struct pci_dev *pdev = to_pci_dev(hwdev); struct dmar_domain *domain; - unsigned long start_addr; + unsigned long start_pfn, last_pfn; struct iova *iova; - size_t size = 0; - phys_addr_t addr; - struct scatterlist *sg; struct intel_iommu *iommu; if (iommu_no_mapping(pdev)) @@ -2709,21 +2703,19 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); if (!iova) return; - for_each_sg(sglist, sg, nelems, i) { - addr = page_to_phys(sg_page(sg)) + sg->offset; - size += aligned_size((u64)addr, sg->length); - } - start_addr = iova->pfn_lo << PAGE_SHIFT; + start_pfn = mm_to_dma_pfn(iova->pfn_lo); + last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1; /* clear the whole page */ - dma_pte_clear_range(domain, start_addr >> VTD_PAGE_SHIFT, - (start_addr + size - 1) >> VTD_PAGE_SHIFT); + dma_pte_clear_range(domain, start_pfn, last_pfn); + /* free page tables */ - dma_pte_free_pagetable(domain, start_addr, start_addr + size); + dma_pte_free_pagetable(domain, start_pfn, last_pfn); - iommu_flush_iotlb_psi(iommu, domain->id, start_addr, - size >> VTD_PAGE_SHIFT); + iommu_flush_iotlb_psi(iommu, domain->id, + start_pfn << VTD_PAGE_SHIFT, + (last_pfn - start_pfn + 1)); /* free iova */ __free_iova(&domain->iovad, iova); @@ -2804,8 +2796,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne start_addr >> VTD_PAGE_SHIFT, (start_addr + offset - 1) >> VTD_PAGE_SHIFT); /* free page tables */ - dma_pte_free_pagetable(domain, start_addr, - start_addr + offset); + dma_pte_free_pagetable(domain, start_addr >> VTD_PAGE_SHIFT, + (start_addr + offset - 1) >> VTD_PAGE_SHIFT); /* free iova */ __free_iova(&domain->iovad, iova); return 0; @@ -3378,8 +3370,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) static void vm_domain_exit(struct dmar_domain *domain) { - u64 end; - /* Domain 0 is reserved, so dont process it */ if (!domain) return; @@ -3387,14 +3377,12 @@ static void vm_domain_exit(struct dmar_domain *domain) vm_domain_remove_all_dev_info(domain); /* destroy iovas */ put_iova_domain(&domain->iovad); - end = DOMAIN_MAX_ADDR(domain->gaw); - end = end & (~VTD_PAGE_MASK); /* clear ptes */ dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); /* free page tables */ - dma_pte_free_pagetable(domain, 0, end); + dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); iommu_free_vm_domain(domain); free_domain_mem(domain); -- GitLab From 163cc52ccd2cc5c5ae4e1c886f6fde8547feed2a Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 00:51:17 +0100 Subject: [PATCH 0347/1002] intel-iommu: Clean up intel_iommu_unmap_range() Use unaligned address for domain->max_addr. That algorithm isn't ideal anyway -- we should probably just look at the last iova in the tree. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fc593adb049a7..21dc77311863a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3491,7 +3491,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) prot |= DMA_PTE_SNP; - max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size); + max_addr = iova + size; if (dmar_domain->max_addr < max_addr) { int min_agaw; u64 end; @@ -3518,16 +3518,12 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, size_t size) { struct dmar_domain *dmar_domain = domain->priv; - dma_addr_t base; - /* The address might not be aligned */ - base = iova & VTD_PAGE_MASK; - size = VTD_PAGE_ALIGN(size); - dma_pte_clear_range(dmar_domain, base >> VTD_PAGE_SHIFT, - (base + size - 1) >> VTD_PAGE_SHIFT); + dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, + (iova + size - 1) >> VTD_PAGE_SHIFT); - if (dmar_domain->max_addr == base + size) - dmar_domain->max_addr = base; + if (dmar_domain->max_addr == iova + size) + dmar_domain->max_addr = iova; } static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, -- GitLab From d6d3f08b0fd998b647a05540cedd11a067b72867 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt <jengelh@medozas.de> Date: Mon, 29 Jun 2009 14:31:46 +0200 Subject: [PATCH 0348/1002] netfilter: xtables: conntrack match revision 2 As reported by Philip, the UNTRACKED state bit does not fit within the 8-bit state_mask member. Enlarge state_mask and give status_mask a few more bits too. Reported-by: Philip Craig <philipc@snapgear.com> References: http://markmail.org/thread/b7eg6aovfh4agyz7 Signed-off-by: Jan Engelhardt <jengelh@medozas.de> Signed-off-by: Patrick McHardy <kaber@trash.net> --- include/linux/netfilter/xt_conntrack.h | 13 +++++ net/netfilter/xt_conntrack.c | 66 +++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 3430c77519482..7ae05338e94c3 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -81,4 +81,17 @@ struct xt_conntrack_mtinfo1 { __u8 state_mask, status_mask; }; +struct xt_conntrack_mtinfo2 { + union nf_inet_addr origsrc_addr, origsrc_mask; + union nf_inet_addr origdst_addr, origdst_mask; + union nf_inet_addr replsrc_addr, replsrc_mask; + union nf_inet_addr repldst_addr, repldst_mask; + __u32 expires_min, expires_max; + __u16 l4proto; + __be16 origsrc_port, origdst_port; + __be16 replsrc_port, repldst_port; + __u16 match_flags, invert_flags; + __u16 state_mask, status_mask; +}; + #endif /*_XT_CONNTRACK_H*/ diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 0b7139f3dd786..fc581800698e6 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -129,7 +129,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr, static inline bool conntrack_mt_origsrc(const struct nf_conn *ct, - const struct xt_conntrack_mtinfo1 *info, + const struct xt_conntrack_mtinfo2 *info, u_int8_t family) { return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, @@ -138,7 +138,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct, static inline bool conntrack_mt_origdst(const struct nf_conn *ct, - const struct xt_conntrack_mtinfo1 *info, + const struct xt_conntrack_mtinfo2 *info, u_int8_t family) { return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, @@ -147,7 +147,7 @@ conntrack_mt_origdst(const struct nf_conn *ct, static inline bool conntrack_mt_replsrc(const struct nf_conn *ct, - const struct xt_conntrack_mtinfo1 *info, + const struct xt_conntrack_mtinfo2 *info, u_int8_t family) { return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, @@ -156,7 +156,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct, static inline bool conntrack_mt_repldst(const struct nf_conn *ct, - const struct xt_conntrack_mtinfo1 *info, + const struct xt_conntrack_mtinfo2 *info, u_int8_t family) { return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, @@ -164,7 +164,7 @@ conntrack_mt_repldst(const struct nf_conn *ct, } static inline bool -ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, +ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, const struct nf_conn *ct) { const struct nf_conntrack_tuple *tuple; @@ -204,7 +204,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, static bool conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) { - const struct xt_conntrack_mtinfo1 *info = par->matchinfo; + const struct xt_conntrack_mtinfo2 *info = par->matchinfo; enum ip_conntrack_info ctinfo; const struct nf_conn *ct; unsigned int statebit; @@ -278,6 +278,16 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) return true; } +static bool +conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) +{ + const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; + struct xt_match_param newpar = *par; + + newpar.matchinfo = *info; + return conntrack_mt(skb, &newpar); +} + static bool conntrack_mt_check(const struct xt_mtchk_param *par) { if (nf_ct_l3proto_try_module_get(par->family) < 0) { @@ -288,11 +298,45 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par) return true; } +static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) +{ + struct xt_conntrack_mtinfo1 *info = par->matchinfo; + struct xt_conntrack_mtinfo2 *up; + int ret = conntrack_mt_check(par); + + if (ret < 0) + return ret; + + up = kmalloc(sizeof(*up), GFP_KERNEL); + if (up == NULL) { + nf_ct_l3proto_module_put(par->family); + return -ENOMEM; + } + + /* + * The strategy here is to minimize the overhead of v1 matching, + * by prebuilding a v2 struct and putting the pointer into the + * v1 dataspace. + */ + memcpy(up, info, offsetof(typeof(*info), state_mask)); + up->state_mask = info->state_mask; + up->status_mask = info->status_mask; + *(void **)info = up; + return true; +} + static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) { nf_ct_l3proto_module_put(par->family); } +static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) +{ + struct xt_conntrack_mtinfo2 **info = par->matchinfo; + kfree(*info); + conntrack_mt_destroy(par); +} + #ifdef CONFIG_COMPAT struct compat_xt_conntrack_info { @@ -363,6 +407,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { .revision = 1, .family = NFPROTO_UNSPEC, .matchsize = sizeof(struct xt_conntrack_mtinfo1), + .match = conntrack_mt_v1, + .checkentry = conntrack_mt_check_v1, + .destroy = conntrack_mt_destroy_v1, + .me = THIS_MODULE, + }, + { + .name = "conntrack", + .revision = 2, + .family = NFPROTO_UNSPEC, + .matchsize = sizeof(struct xt_conntrack_mtinfo2), .match = conntrack_mt, .checkentry = conntrack_mt_check, .destroy = conntrack_mt_destroy, -- GitLab From b026fd28ea23af24a3eea6e5be3f3d0193a8e87d Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 10:37:25 +0100 Subject: [PATCH 0349/1002] intel-iommu: Change addr_to_dma_pte() to pfn_to_dma_pte() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 21dc77311863a..dfbabd151a9c8 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -692,23 +692,24 @@ static inline unsigned long align_to_level(unsigned long pfn, int level) return (pfn + level_size(level) - 1) & level_mask(level); } -static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) +static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, + unsigned long pfn) { - int addr_width = agaw_to_width(domain->agaw); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; struct dma_pte *parent, *pte = NULL; int level = agaw_to_level(domain->agaw); int offset; unsigned long flags; BUG_ON(!domain->pgd); - BUG_ON(addr >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); parent = domain->pgd; spin_lock_irqsave(&domain->mapping_lock, flags); while (level > 0) { void *tmp_page; - offset = pfn_level_offset(addr >> VTD_PAGE_SHIFT, level); + offset = pfn_level_offset(pfn, level); pte = &parent[offset]; if (level == 1) break; @@ -1660,7 +1661,7 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; index = 0; while (start_pfn < end_pfn) { - pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index); + pte = pfn_to_dma_pte(domain, (iova >> VTD_PAGE_SHIFT) + index); if (!pte) return -ENOMEM; /* We don't need lock here, nobody else @@ -3533,7 +3534,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, struct dma_pte *pte; u64 phys = 0; - pte = addr_to_dma_pte(dmar_domain, iova); + pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT); if (pte) phys = dma_pte_addr(pte); -- GitLab From 1c5a46ed49e37f56f8aa9000bb1c2ac59670c372 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 10:53:37 +0100 Subject: [PATCH 0350/1002] intel-iommu: Clean up address handling in domain_page_mapping() No more masking and alignment; just use pfns. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index dfbabd151a9c8..f08d7865fe006 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1647,20 +1647,18 @@ static int domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, u64 hpa, size_t size, int prot) { - u64 start_pfn, end_pfn; + unsigned long start_pfn = hpa >> VTD_PAGE_SHIFT; + unsigned long last_pfn = (hpa + size - 1) >> VTD_PAGE_SHIFT; struct dma_pte *pte; - int index; - int addr_width = agaw_to_width(domain->agaw); + int index = 0; + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - BUG_ON(hpa >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) return -EINVAL; - iova &= PAGE_MASK; - start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT; - end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT; - index = 0; - while (start_pfn < end_pfn) { + + while (start_pfn <= last_pfn) { pte = pfn_to_dma_pte(domain, (iova >> VTD_PAGE_SHIFT) + index); if (!pte) return -ENOMEM; -- GitLab From 61df744314079e8cb8cdec75f517cf0e704e41ef Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 11:55:58 +0100 Subject: [PATCH 0351/1002] intel-iommu: Introduce domain_pfn_mapping() ... and use it in the trivial cases; the other callers want individual (and bisectable) attention, since I screwed them up the first time... Make the BUG_ON() happen on too-large virtual address rather than physical address, too. That's the one we care about. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f08d7865fe006..7540ef91d5f7c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1643,40 +1643,48 @@ static int domain_context_mapped(struct pci_dev *pdev) tmp->devfn); } -static int -domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, - u64 hpa, size_t size, int prot) +static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + unsigned long phys_pfn, unsigned long nr_pages, + int prot) { - unsigned long start_pfn = hpa >> VTD_PAGE_SHIFT; - unsigned long last_pfn = (hpa + size - 1) >> VTD_PAGE_SHIFT; struct dma_pte *pte; - int index = 0; int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); + BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) return -EINVAL; - while (start_pfn <= last_pfn) { - pte = pfn_to_dma_pte(domain, (iova >> VTD_PAGE_SHIFT) + index); + while (nr_pages--) { + pte = pfn_to_dma_pte(domain, iov_pfn); if (!pte) return -ENOMEM; /* We don't need lock here, nobody else * touches the iova range */ BUG_ON(dma_pte_addr(pte)); - dma_set_pte_pfn(pte, start_pfn); + dma_set_pte_pfn(pte, phys_pfn); dma_set_pte_prot(pte, prot); if (prot & DMA_PTE_SNP) dma_set_pte_snp(pte); domain_flush_cache(domain, pte, sizeof(*pte)); - start_pfn++; - index++; + iov_pfn++; + phys_pfn++; } return 0; } +static int domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, + u64 hpa, size_t size, int prot) +{ + unsigned long first_pfn = hpa >> VTD_PAGE_SHIFT; + unsigned long last_pfn = (hpa + size - 1) >> VTD_PAGE_SHIFT; + + return domain_pfn_mapping(domain, iova >> VTD_PAGE_SHIFT, first_pfn, + last_pfn - first_pfn + 1, prot); + +} + static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) { if (!iommu) @@ -1893,8 +1901,10 @@ static int iommu_domain_identity_map(struct dmar_domain *domain, dma_pte_clear_range(domain, base >> VTD_PAGE_SHIFT, (base + size - 1) >> VTD_PAGE_SHIFT); - return domain_page_mapping(domain, base, base, size, - DMA_PTE_READ|DMA_PTE_WRITE); + return domain_pfn_mapping(domain, base >> VTD_PAGE_SHIFT, + base >> VTD_PAGE_SHIFT, + size >> VTD_PAGE_SHIFT, + DMA_PTE_READ|DMA_PTE_WRITE); } static int iommu_prepare_identity_map(struct pci_dev *pdev, -- GitLab From 0ab36de274ab094c3992b50c9c48c5c89072ec94 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 14:01:43 +0100 Subject: [PATCH 0352/1002] intel-iommu: Use domain_pfn_mapping() in __intel_map_single() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 7540ef91d5f7c..dccd0a7b7a5fc 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2477,14 +2477,12 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, return 0; iommu = domain_get_iommu(domain); - size = aligned_size((u64)paddr, size); + size = aligned_size(paddr, size) >> VTD_PAGE_SHIFT; - iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, pdev->dma_mask); if (!iova) goto error; - start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; - /* * Check if DMAR supports zero-length reads on write only * mappings.. @@ -2500,20 +2498,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, * might have two guest_addr mapping to the same host paddr, but this * is not a big problem */ - ret = domain_page_mapping(domain, start_paddr, - ((u64)paddr) & PHYSICAL_PAGE_MASK, - size, prot); + ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo), + paddr >> VTD_PAGE_SHIFT, size, prot); if (ret) goto error; + start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; + /* it's a non-present to present mapping. Only flush if caching mode */ if (cap_caching_mode(iommu->cap)) - iommu_flush_iotlb_psi(iommu, 0, start_paddr, - size >> VTD_PAGE_SHIFT); + iommu_flush_iotlb_psi(iommu, 0, start_paddr, size); else iommu_flush_write_buffer(iommu); - return start_paddr + ((u64)paddr & (~PAGE_MASK)); + return start_paddr + (paddr & (~PAGE_MASK)); error: if (iova) -- GitLab From ad05122162b67f64d5a1c6d35e001f7a88619b88 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 14:22:28 +0100 Subject: [PATCH 0353/1002] intel-iommu: Use domain_pfn_mapping() in intel_iommu_map_range() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index dccd0a7b7a5fc..a490b39ca3d57 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3516,8 +3516,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain, } dmar_domain->max_addr = max_addr; } - - ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot); + /* Round up size to next multiple of PAGE_SIZE, if it and + the low bits of hpa would take us onto the next page */ + size = aligned_size(hpa, size) >> VTD_PAGE_SHIFT; + ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, + hpa >> VTD_PAGE_SHIFT, size, prot); return ret; } -- GitLab From b536d24d212c994a7d98469ea3a8891573d45fd4 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 14:49:31 +0100 Subject: [PATCH 0354/1002] intel-iommu: Clean up intel_map_sg(), remove domain_page_mapping() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 54 ++++++++++++++------------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a490b39ca3d57..bc49b121c667a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1674,17 +1674,6 @@ static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, return 0; } -static int domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, - u64 hpa, size_t size, int prot) -{ - unsigned long first_pfn = hpa >> VTD_PAGE_SHIFT; - unsigned long last_pfn = (hpa + size - 1) >> VTD_PAGE_SHIFT; - - return domain_pfn_mapping(domain, iova >> VTD_PAGE_SHIFT, first_pfn, - last_pfn - first_pfn + 1, prot); - -} - static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) { if (!iommu) @@ -2745,17 +2734,16 @@ static int intel_nontranslate_map_sg(struct device *hddev, static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems, enum dma_data_direction dir, struct dma_attrs *attrs) { - phys_addr_t addr; int i; struct pci_dev *pdev = to_pci_dev(hwdev); struct dmar_domain *domain; size_t size = 0; int prot = 0; - size_t offset = 0; + size_t offset_pfn = 0; struct iova *iova = NULL; int ret; struct scatterlist *sg; - unsigned long start_addr; + unsigned long start_vpfn; struct intel_iommu *iommu; BUG_ON(dir == DMA_NONE); @@ -2768,10 +2756,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne iommu = domain_get_iommu(domain); - for_each_sg(sglist, sg, nelems, i) { - addr = page_to_phys(sg_page(sg)) + sg->offset; - size += aligned_size((u64)addr, sg->length); - } + for_each_sg(sglist, sg, nelems, i) + size += aligned_size(sg->offset, sg->length); iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); if (!iova) { @@ -2789,36 +2775,34 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) prot |= DMA_PTE_WRITE; - start_addr = iova->pfn_lo << PAGE_SHIFT; - offset = 0; + start_vpfn = mm_to_dma_pfn(iova->pfn_lo); + offset_pfn = 0; for_each_sg(sglist, sg, nelems, i) { - addr = page_to_phys(sg_page(sg)) + sg->offset; - size = aligned_size((u64)addr, sg->length); - ret = domain_page_mapping(domain, start_addr + offset, - ((u64)addr) & PHYSICAL_PAGE_MASK, - size, prot); + int nr_pages = aligned_size(sg->offset, sg->length) >> VTD_PAGE_SHIFT; + ret = domain_pfn_mapping(domain, start_vpfn + offset_pfn, + page_to_dma_pfn(sg_page(sg)), + nr_pages, prot); if (ret) { /* clear the page */ - dma_pte_clear_range(domain, - start_addr >> VTD_PAGE_SHIFT, - (start_addr + offset - 1) >> VTD_PAGE_SHIFT); + dma_pte_clear_range(domain, start_vpfn, + start_vpfn + offset_pfn); /* free page tables */ - dma_pte_free_pagetable(domain, start_addr >> VTD_PAGE_SHIFT, - (start_addr + offset - 1) >> VTD_PAGE_SHIFT); + dma_pte_free_pagetable(domain, start_vpfn, + start_vpfn + offset_pfn); /* free iova */ __free_iova(&domain->iovad, iova); return 0; } - sg->dma_address = start_addr + offset + - ((u64)addr & (~PAGE_MASK)); + sg->dma_address = ((dma_addr_t)(start_vpfn + offset_pfn) + << VTD_PAGE_SHIFT) + sg->offset; sg->dma_length = sg->length; - offset += size; + offset_pfn += nr_pages; } /* it's a non-present to present mapping. Only flush if caching mode */ if (cap_caching_mode(iommu->cap)) - iommu_flush_iotlb_psi(iommu, 0, start_addr, - offset >> VTD_PAGE_SHIFT); + iommu_flush_iotlb_psi(iommu, 0, start_vpfn << VTD_PAGE_SHIFT, + offset_pfn); else iommu_flush_write_buffer(iommu); -- GitLab From 88cb6a7424d9465faf6caaaadff5af0766c93991 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 15:03:06 +0100 Subject: [PATCH 0355/1002] intel-iommu: Change aligned_size() to aligned_nrpages() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index bc49b121c667a..22add36fd7310 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2320,11 +2320,13 @@ int __init init_dmars(void) return ret; } -static inline u64 aligned_size(u64 host_addr, size_t size) +static inline unsigned long aligned_nrpages(unsigned long host_addr, + size_t size) { - u64 addr; - addr = (host_addr & (~PAGE_MASK)) + size; - return PAGE_ALIGN(addr); + host_addr &= ~PAGE_MASK; + host_addr += size + PAGE_SIZE - 1; + + return host_addr >> VTD_PAGE_SHIFT; } struct iova * @@ -2466,7 +2468,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, return 0; iommu = domain_get_iommu(domain); - size = aligned_size(paddr, size) >> VTD_PAGE_SHIFT; + size = aligned_nrpages(paddr, size); iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, pdev->dma_mask); if (!iova) @@ -2757,9 +2759,10 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne iommu = domain_get_iommu(domain); for_each_sg(sglist, sg, nelems, i) - size += aligned_size(sg->offset, sg->length); + size += aligned_nrpages(sg->offset, sg->length); - iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, + pdev->dma_mask); if (!iova) { sglist->dma_length = 0; return 0; @@ -2778,7 +2781,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne start_vpfn = mm_to_dma_pfn(iova->pfn_lo); offset_pfn = 0; for_each_sg(sglist, sg, nelems, i) { - int nr_pages = aligned_size(sg->offset, sg->length) >> VTD_PAGE_SHIFT; + int nr_pages = aligned_nrpages(sg->offset, sg->length); ret = domain_pfn_mapping(domain, start_vpfn + offset_pfn, page_to_dma_pfn(sg_page(sg)), nr_pages, prot); @@ -3502,7 +3505,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, } /* Round up size to next multiple of PAGE_SIZE, if it and the low bits of hpa would take us onto the next page */ - size = aligned_size(hpa, size) >> VTD_PAGE_SHIFT; + size = aligned_nrpages(hpa, size); ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT, hpa >> VTD_PAGE_SHIFT, size, prot); return ret; -- GitLab From 03d6a2461ab1704c171ce21081c5022378ef7a91 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 15:33:46 +0100 Subject: [PATCH 0356/1002] intel-iommu: Make iommu_flush_iotlb_psi() take pfn as argument Most of its callers are having to shift for themselves anyway, so we might as well do it in iommu_flush_iotlb_psi(). Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 22add36fd7310..6afe44cb68152 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1058,11 +1058,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, } static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, - u64 addr, unsigned int pages) + unsigned long pfn, unsigned int pages) { unsigned int mask = ilog2(__roundup_pow_of_two(pages)); + uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; - BUG_ON(addr & (~VTD_PAGE_MASK)); BUG_ON(pages == 0); /* @@ -2494,15 +2494,15 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, if (ret) goto error; - start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; - /* it's a non-present to present mapping. Only flush if caching mode */ if (cap_caching_mode(iommu->cap)) - iommu_flush_iotlb_psi(iommu, 0, start_paddr, size); + iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); else iommu_flush_write_buffer(iommu); - return start_paddr + (paddr & (~PAGE_MASK)); + start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT; + start_paddr += paddr & ~PAGE_MASK; + return start_paddr; error: if (iova) @@ -2624,8 +2624,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, dma_pte_free_pagetable(domain, start_pfn, last_pfn); if (intel_iommu_strict) { - iommu_flush_iotlb_psi(iommu, domain->id, - start_pfn << VTD_PAGE_SHIFT, + iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, last_pfn - start_pfn + 1); /* free iova */ __free_iova(&domain->iovad, iova); @@ -2711,8 +2710,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, /* free page tables */ dma_pte_free_pagetable(domain, start_pfn, last_pfn); - iommu_flush_iotlb_psi(iommu, domain->id, - start_pfn << VTD_PAGE_SHIFT, + iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, (last_pfn - start_pfn + 1)); /* free iova */ @@ -2804,8 +2802,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne /* it's a non-present to present mapping. Only flush if caching mode */ if (cap_caching_mode(iommu->cap)) - iommu_flush_iotlb_psi(iommu, 0, start_vpfn << VTD_PAGE_SHIFT, - offset_pfn); + iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); else iommu_flush_write_buffer(iommu); -- GitLab From 1a4a45516d7a57de0691352d899d7008f2e090d1 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 16:00:42 +0100 Subject: [PATCH 0357/1002] intel-iommu: Remove last use of PHYSICAL_PAGE_MASK, for reserving PCI BARs This is fairly broken anyway -- it doesn't take hotplug into account. We should probably be checking page_is_ram() instead. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 6afe44cb68152..a55f5fb06b147 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -62,9 +62,6 @@ #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) -#ifndef PHYSICAL_PAGE_MASK -#define PHYSICAL_PAGE_MASK PAGE_MASK -#endif /* VT-d pages must always be _smaller_ than MM pages. Otherwise things are never going to work. */ @@ -1307,7 +1304,6 @@ static void dmar_init_reserved_ranges(void) struct pci_dev *pdev = NULL; struct iova *iova; int i; - u64 addr, size; init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); @@ -1330,12 +1326,9 @@ static void dmar_init_reserved_ranges(void) r = &pdev->resource[i]; if (!r->flags || !(r->flags & IORESOURCE_MEM)) continue; - addr = r->start; - addr &= PHYSICAL_PAGE_MASK; - size = r->end - addr; - size = PAGE_ALIGN(size); - iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), - IOVA_PFN(size + addr) - 1); + iova = reserve_iova(&reserved_iova_list, + IOVA_PFN(r->start), + IOVA_PFN(r->end)); if (!iova) printk(KERN_ERR "Reserve iova failed\n"); } -- GitLab From c5395d5c4a82159889cb650de93b591ea51d8c56 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 16:35:56 +0100 Subject: [PATCH 0358/1002] intel-iommu: Clean up iommu_domain_identity_map() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a55f5fb06b147..c5caf7d63a0f9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1861,31 +1861,25 @@ static int iommu_domain_identity_map(struct dmar_domain *domain, unsigned long long start, unsigned long long end) { - unsigned long size; - unsigned long long base; + unsigned long first_vpfn = start >> VTD_PAGE_SHIFT; + unsigned long last_vpfn = end >> VTD_PAGE_SHIFT; - /* The address might not be aligned */ - base = start & PAGE_MASK; - size = end - base; - size = PAGE_ALIGN(size); - if (!reserve_iova(&domain->iovad, IOVA_PFN(base), - IOVA_PFN(base + size) - 1)) { + if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn), + dma_to_mm_pfn(last_vpfn))) { printk(KERN_ERR "IOMMU: reserve iova failed\n"); return -ENOMEM; } - pr_debug("Mapping reserved region %lx@%llx for domain %d\n", - size, base, domain->id); + pr_debug("Mapping reserved region %llx-%llx for domain %d\n", + start, end, domain->id); /* * RMRR range might have overlap with physical memory range, * clear it first */ - dma_pte_clear_range(domain, base >> VTD_PAGE_SHIFT, - (base + size - 1) >> VTD_PAGE_SHIFT); + dma_pte_clear_range(domain, first_vpfn, last_vpfn); - return domain_pfn_mapping(domain, base >> VTD_PAGE_SHIFT, - base >> VTD_PAGE_SHIFT, - size >> VTD_PAGE_SHIFT, + return domain_pfn_mapping(domain, first_vpfn, first_vpfn, + last_vpfn - first_vpfn + 1, DMA_PTE_READ|DMA_PTE_WRITE); } -- GitLab From 310a5ab93cb4ce29367238f682affd9ac352f4d0 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 18:52:20 +0100 Subject: [PATCH 0359/1002] intel-iommu: Performance improvement for dma_pte_clear_range() It's a bit silly to repeatedly call domain_flush_cache() for each PTE individually, as we clear it. Instead, batch them up and flush a whole range at a time. We might as well refrain from recalculating the PTE address from scratch each time round the loop too. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c5caf7d63a0f9..ba7e37f7111ad 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -761,34 +761,33 @@ static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, return NULL; } -/* clear one page's page table */ -static void dma_pte_clear_one(struct dmar_domain *domain, unsigned long pfn) -{ - struct dma_pte *pte = NULL; - - /* get last level pte */ - pte = dma_pfn_level_pte(domain, pfn, 1); - - if (pte) { - dma_clear_pte(pte); - domain_flush_cache(domain, pte, sizeof(*pte)); - } -} - /* clear last level pte, a tlb flush should be followed */ static void dma_pte_clear_range(struct dmar_domain *domain, unsigned long start_pfn, unsigned long last_pfn) { int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; + struct dma_pte *first_pte, *pte; BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); /* we don't need lock here; nobody else touches the iova range */ while (start_pfn <= last_pfn) { - dma_pte_clear_one(domain, start_pfn); - start_pfn++; + first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); + if (!pte) { + start_pfn = align_to_level(start_pfn + 1, 2); + continue; + } + while (start_pfn <= last_pfn && + (unsigned long)pte >> VTD_PAGE_SHIFT == + (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + dma_clear_pte(pte); + start_pfn++; + pte++; + } + domain_flush_cache(domain, first_pte, + (void *)pte - (void *)first_pte); } } -- GitLab From 6f6a00e40aa3fdd3b29c30e3ef1fc9690506bc03 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 20:38:49 +0100 Subject: [PATCH 0360/1002] intel-iommu: Performance improvement for domain_pfn_mapping() As with dma_pte_clear_range(), don't keep flushing a single PTE at a time. And also micro-optimise the setting of PTE values rather than using the helper functions to do all the masking. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ba7e37f7111ad..f8074236bcce1 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1639,7 +1639,7 @@ static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, unsigned long phys_pfn, unsigned long nr_pages, int prot) { - struct dma_pte *pte; + struct dma_pte *first_pte = NULL, *pte = NULL; int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); @@ -1647,19 +1647,27 @@ static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) return -EINVAL; + prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + while (nr_pages--) { - pte = pfn_to_dma_pte(domain, iov_pfn); - if (!pte) - return -ENOMEM; + if (!pte) { + first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); + if (!pte) + return -ENOMEM; + } /* We don't need lock here, nobody else * touches the iova range */ BUG_ON(dma_pte_addr(pte)); - dma_set_pte_pfn(pte, phys_pfn); - dma_set_pte_prot(pte, prot); - if (prot & DMA_PTE_SNP) - dma_set_pte_snp(pte); - domain_flush_cache(domain, pte, sizeof(*pte)); + pte->val = (phys_pfn << VTD_PAGE_SHIFT) | prot; + pte++; + if (!nr_pages || + (unsigned long)pte >> VTD_PAGE_SHIFT != + (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + domain_flush_cache(domain, first_pte, + (void *)pte - (void *)first_pte); + pte = NULL; + } iov_pfn++; phys_pfn++; } -- GitLab From 875764de6f0ddb23d270c29357d5a339232a0488 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sun, 28 Jun 2009 21:20:51 +0100 Subject: [PATCH 0361/1002] intel-iommu: Simplify __intel_alloc_iova() There's no need for the separate iommu_alloc_iova() function, and certainly not for it to be global. Remove the underscores while we're at it. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 49 ++++++++++++++------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f8074236bcce1..11a23201445a4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2323,43 +2323,31 @@ static inline unsigned long aligned_nrpages(unsigned long host_addr, return host_addr >> VTD_PAGE_SHIFT; } -struct iova * -iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) -{ - struct iova *piova; - - /* Make sure it's in range */ - end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); - if (!size || (IOVA_START_ADDR + size > end)) - return NULL; - - piova = alloc_iova(&domain->iovad, - size >> PAGE_SHIFT, IOVA_PFN(end), 1); - return piova; -} - -static struct iova * -__intel_alloc_iova(struct device *dev, struct dmar_domain *domain, - size_t size, u64 dma_mask) +static struct iova *intel_alloc_iova(struct device *dev, + struct dmar_domain *domain, + unsigned long nrpages, uint64_t dma_mask) { struct pci_dev *pdev = to_pci_dev(dev); struct iova *iova = NULL; - if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) - iova = iommu_alloc_iova(domain, size, dma_mask); - else { + /* Restrict dma_mask to the width that the iommu can handle */ + dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); + + if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { /* * First try to allocate an io virtual address in * DMA_BIT_MASK(32) and if that fails then try allocating * from higher range */ - iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); - if (!iova) - iova = iommu_alloc_iova(domain, size, dma_mask); - } - - if (!iova) { - printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); + iova = alloc_iova(&domain->iovad, nrpages, + IOVA_PFN(DMA_BIT_MASK(32)), 1); + if (iova) + return iova; + } + iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); + if (unlikely(!iova)) { + printk(KERN_ERR "Allocating %ld-page iova for %s failed", + nrpages, pci_name(pdev)); return NULL; } @@ -2464,7 +2452,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, iommu = domain_get_iommu(domain); size = aligned_nrpages(paddr, size); - iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); if (!iova) goto error; @@ -2753,8 +2741,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne for_each_sg(sglist, sg, nelems, i) size += aligned_nrpages(sg->offset, sg->length); - iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, - pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); if (!iova) { sglist->dma_length = 0; return 0; -- GitLab From e6ce3066010a21bde961d8f8cefe0b69cae78a0f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr <jk@ozlabs.org> Date: Mon, 29 Jun 2009 14:31:58 +0800 Subject: [PATCH 0362/1002] fs: allow d_instantiate to be called with negative parent dentry The new fsnotify infrastructure (starting at 90586523) causes an oops in spufs, where we populate a directory with files before instantiating the directory itself. The new changes seem to have introduced an assumption that a dentry's parent will be positive when instantiating. This change makes it once again possible to d_instantiate a dentry with a negative parent, and brings __fsnotify_d_instantiate() into line with inotify_d_instantiate(), which already has this NULL check. Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Eric Paris <eparis@redhat.com> --- include/linux/fsnotify_backend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 44848aa830dcd..6c3de999fb348 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -280,7 +280,7 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) assert_spin_locked(&dentry->d_lock); parent = dentry->d_parent; - if (fsnotify_inode_watches_children(parent->d_inode)) + if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode)) dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED; else dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED; -- GitLab From e0af6062aa4f89081afb8a1a4269605775d354de Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Date: Thu, 18 Jun 2009 13:05:49 +0400 Subject: [PATCH 0363/1002] MAINTAINERS: ieee802154 lists are moderated for non-subscribers. Note that our mailing list is moderated for non-subscribers. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fa2a16def17af..28c150e916a2c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2886,7 +2886,7 @@ P: Dmitry Eremin-Solenikov M: dbaryshkov@gmail.com P: Sergey Lapin M: slapin@ossfans.org -L: linux-zigbee-devel@lists.sourceforge.net +L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://apps.sourceforge.net/trac/linux-zigbee T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git S: Maintained -- GitLab From 932c1329acebc03ef5efa3647c9c3a967b59d0c4 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Date: Fri, 19 Jun 2009 17:00:08 +0400 Subject: [PATCH 0364/1002] nl802154: fix Oops in ieee802154_nl_get_dev ieee802154_nl_get_dev() lacks check for the existance of the device that was returned by dev_get_XXX, thus resulting in Oops for non-existing devices. Fix it. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> --- net/ieee802154/netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 105ad10876afe..332b947ae8122 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -276,6 +276,9 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) else return NULL; + if (!dev) + return NULL; + if (dev->type != ARPHRD_IEEE802154) { dev_put(dev); return NULL; -- GitLab From dfd06fe8246c0425f8d6850b8e2c872b0d691ec3 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Date: Fri, 19 Jun 2009 17:02:09 +0400 Subject: [PATCH 0365/1002] nl802154: add module license and description Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> --- net/ieee802154/netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 332b947ae8122..27eda9fdf3c20 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -524,3 +524,6 @@ static void __exit ieee802154_nl_exit(void) } module_exit(ieee802154_nl_exit); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("ieee 802.15.4 configuration interface"); + -- GitLab From 9ea5ca75a2aebb7172094a7d77acf6ff7600cc56 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Mon, 29 Jun 2009 18:03:34 +0200 Subject: [PATCH 0366/1002] sound: OSS: mpu401, fix deadlock mpu401_chk_version is called with a spin lock already held. Don't take it again. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/oss/mpu401.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 6c0a770ed0543..1b2316f35b1f9 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c @@ -926,31 +926,21 @@ static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; static void mpu401_chk_version(int n, struct mpu_config *devc) { int tmp; - unsigned long flags; devc->version = devc->revision = 0; - spin_lock_irqsave(&devc->lock,flags); - if ((tmp = mpu_cmd(n, 0xAC, 0)) < 0) - { - spin_unlock_irqrestore(&devc->lock,flags); + tmp = mpu_cmd(n, 0xAC, 0); + if (tmp < 0) return; - } if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - { - spin_unlock_irqrestore(&devc->lock,flags); return; - } devc->version = tmp; - if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) - { + if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) { devc->version = 0; - spin_unlock_irqrestore(&devc->lock,flags); return; } devc->revision = tmp; - spin_unlock_irqrestore(&devc->lock,flags); } int attach_mpu401(struct address_info *hw_config, struct module *owner) -- GitLab From 17bb9e0d906b625f86e9d31740bb1c35bc0f63d7 Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Mon, 29 Jun 2009 17:13:56 +0100 Subject: [PATCH 0367/1002] kmemleak: Do not report new leaked objects if the scanning was stopped If the scanning was stopped with a signal, it is possible that some objects are left with a white colour (potential leaks) and reported. Add a check to avoid reporting such objects. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- mm/kmemleak.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c37e8e50e4dee..e094c4dbdf55b 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1029,6 +1029,12 @@ static void kmemleak_scan(void) } WARN_ON(!list_empty(&gray_list)); + /* + * If scanning was stopped do not report any new unreferenced objects. + */ + if (scan_should_stop()) + return; + /* * Scanning result reporting. */ @@ -1184,11 +1190,10 @@ static int kmemleak_seq_show(struct seq_file *seq, void *v) unsigned long flags; spin_lock_irqsave(&object->lock, flags); - if (!unreferenced_object(object)) - goto out; - print_unreferenced(seq, object); - reported_leaks++; -out: + if ((object->flags & OBJECT_REPORTED) && unreferenced_object(object)) { + print_unreferenced(seq, object); + reported_leaks++; + } spin_unlock_irqrestore(&object->lock, flags); return 0; } -- GitLab From b6e687221eb840bacd4d4a991e5f8e7ed3ae910a Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Mon, 29 Jun 2009 17:13:57 +0100 Subject: [PATCH 0368/1002] kmemleak: Do not warn if an unknown object is freed vmap'ed memory blocks are not tracked by kmemleak (yet) but they may be released with vfree() which is tracked. The corresponding kmemleak warning is only enabled in debug mode. Future patch will add support for ioremap and vmap. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- mm/kmemleak.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index e094c4dbdf55b..eeece2deace26 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -531,8 +531,10 @@ static void delete_object(unsigned long ptr) write_lock_irqsave(&kmemleak_lock, flags); object = lookup_object(ptr, 0); if (!object) { +#ifdef DEBUG kmemleak_warn("Freeing unknown object at 0x%08lx\n", ptr); +#endif write_unlock_irqrestore(&kmemleak_lock, flags); return; } -- GitLab From 12de38b186c2af97bf0b4a1f907f766df46b1def Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Mon, 29 Jun 2009 17:13:55 +0100 Subject: [PATCH 0369/1002] kmemleak: Inform kmemleak about pid_hash Kmemleak does not track alloc_bootmem calls but the pid_hash allocated in pidhash_init() would need to be scanned as it contains pointers to struct pid objects. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> --- kernel/pid.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/pid.c b/kernel/pid.c index 31310b5d3f503..5fa1db48d8b70 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -36,6 +36,7 @@ #include <linux/pid_namespace.h> #include <linux/init_task.h> #include <linux/syscalls.h> +#include <linux/kmemleak.h> #define pid_hashfn(nr, ns) \ hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift) @@ -512,6 +513,12 @@ void __init pidhash_init(void) pid_hash = alloc_bootmem(pidhash_size * sizeof(*(pid_hash))); if (!pid_hash) panic("Could not alloc pidhash!\n"); + /* + * pid_hash contains references to allocated struct pid objects and it + * must be scanned by kmemleak to avoid false positives. + */ + kmemleak_alloc(pid_hash, pidhash_size * sizeof(*(pid_hash)), 0, + GFP_KERNEL); for (i = 0; i < pidhash_size; i++) INIT_HLIST_HEAD(&pid_hash[i]); } -- GitLab From aef29bc2603014cb28dfe39bab8d888546fe18e7 Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Mon, 29 Jun 2009 15:21:47 +0100 Subject: [PATCH 0370/1002] tty: Fix the leak in tty_ldisc_release Currently we reinit the ldisc on final tty close which is what the old code did to ensure that if the device retained its termios settings then it had the right ldisc. tty_ldisc_reinit does that but also leaves us with the reset ldisc reference which is then leaked. At this point we know the port will be recycled so we can kill the ldisc off completely rather than try and add another ldisc free up when the kref count hits zero. At this point it is safe to keep the ldisc closed as tty_ldisc waiting methods are only used from the user side, and as the final close we are the last such reference. Interrupt/driver side methods will always use the non wait version and get back a NULL. Found with kmemleak and investigated/identified by Catalin Marinas. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/char/tty_ldisc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index a19e935847b0a..913aa8d3f1c5d 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -867,15 +867,22 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) tty_ldisc_wait_idle(tty); /* - * Shutdown the current line discipline, and reset it to N_TTY. - * - * FIXME: this MUST get fixed for the new reflocking + * Now kill off the ldisc */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; + + /* Ensure the next open requests the N_TTY ldisc */ + tty_set_termios_ldisc(tty, N_TTY); - tty_ldisc_reinit(tty); /* This will need doing differently if we need to lock */ if (o_tty) tty_ldisc_release(o_tty, NULL); + + /* And the memory resources remaining (buffers, termios) will be + disposed of when the kref hits zero */ } /** -- GitLab From 44b3615b8cb3b016a49eb7ef4236e77a77793cec Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Mon, 29 Jun 2009 10:07:54 +0200 Subject: [PATCH 0371/1002] eeepc-laptop: Fix build failure with HOTPLUG_PCI && !SYSFS FYI, there's a post-rc1 build regression with certain configs: drivers/built-in.o: In function `pci_hp_deregister': (.text+0xb166): undefined reference to `pci_hp_remove_module_link' drivers/built-in.o: In function `pci_hp_deregister': (.text+0xb19f): undefined reference to `pci_destroy_slot' drivers/built-in.o: In function `__pci_hp_register': (.text+0xb583): undefined reference to `pci_create_slot' drivers/built-in.o: In function `__pci_hp_register': (.text+0xb5b1): undefined reference to `pci_hp_create_module_link' make: *** [.tmp_vmlinux1] Error 1 Caused by: | 2b121bc262fa03c94e653b2d44356c2f86c1bcdc is first bad commit | commit 2b121bc262fa03c94e653b2d44356c2f86c1bcdc | Date: Thu Jun 25 13:25:36 2009 +0200 | | eeepc-laptop: Register as a pci-hotplug device which changed the driver to use the PCI hotplug infrastructure, but didn't do a good job on the Kconfig rules. Signed-off-by: Ingo Molnar <mingo@elte.hu> Acked-by: Randy Dunlap <randy.dunlap@oracle.com> Acked-by: Len Brown <len.brown@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fee6a4022bc17..46dad12f952f2 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -355,10 +355,9 @@ config EEEPC_LAPTOP depends on INPUT depends on EXPERIMENTAL depends on RFKILL || RFKILL = n + depends on HOTPLUG_PCI select BACKLIGHT_CLASS_DEVICE select HWMON - select HOTPLUG - select HOTPLUG_PCI if PCI ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. -- GitLab From 0d07348931daef854aca8c834a89f1a99ba4ff2b Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Wed, 24 Jun 2009 12:08:27 +0900 Subject: [PATCH 0372/1002] PCI MSI: Return if alloc_msi_entry for MSI-X failed In current code it continues setup even if alloc_msi_entry() for MSI-X is failed due to lack of memory. It means arch_setup_msi_irqs() might be called with msi_desc entries less than its argument nvec. At least x86's arch_setup_msi_irqs() uses list_for_each_entry() for dev->msi_list that suspected to have entries same numbers as nvec, and it doesn't check the number of allocated vectors and passed arg nvec. Therefore it will result in success of pci_enable_msix(), with less vectors allocated than requested. This patch fixes the error route to return -ENOMEM, instead of continuing the setup (proposed by Matthew Wilcox). Note that there is no iounmap in msi_free_irqs() if no msi_disc is allocated. Reviewed-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/msi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d9f06fbfa0bf8..628c14150d49f 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -439,8 +439,14 @@ static int msix_capability_init(struct pci_dev *dev, for (i = 0; i < nvec; i++) { entry = alloc_msi_entry(dev); - if (!entry) - break; + if (!entry) { + if (!i) + iounmap(base); + else + msi_free_irqs(dev); + /* No enough memory. Don't try again */ + return -ENOMEM; + } j = entries[i].entry; entry->msi_attrib.is_msix = 1; -- GitLab From 50e5628a4ac465a52f0d4ca6567343be029731a0 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 09:26:40 -0700 Subject: [PATCH 0373/1002] PCI ECRC: Remove unnecessary semicolons Acked-by: Andrew Patterson <andrew.patterson@hp.com> Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/pcie/aer/ecrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c index ece97df4df6d1..a928d8ab6bda2 100644 --- a/drivers/pci/pcie/aer/ecrc.c +++ b/drivers/pci/pcie/aer/ecrc.c @@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev) disable_ecrc_checking(dev); break; case ECRC_POLICY_ON: - enable_ecrc_checking(dev);; + enable_ecrc_checking(dev); break; default: return; -- GitLab From 977badb2f385db14d8ba3fcf02fbd7ead8e63d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Luis=20V=C3=A1zquez=20Cao?= <fernando@oss.ntt.co.jp> Date: Fri, 26 Jun 2009 11:27:41 +0900 Subject: [PATCH 0374/1002] PCI: remove pci_dac_dma_... APIs on mn10300 It seems that mn10300 made it upstream after Jan Beulich's pci_dac_dma_* cleanup work and still defines pci_dac_dma_supported(). This API is not required by the PCI subsystem anymore, so remove it. Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Fernando Luis Vazquez Cao <fernando@oss.ntt.co.jp> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- arch/mn10300/include/asm/pci.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h index e58b9a46e1b14..35d2ed6396f60 100644 --- a/arch/mn10300/include/asm/pci.h +++ b/arch/mn10300/include/asm/pci.h @@ -70,10 +70,6 @@ struct pci_dev; */ #define PCI_DMA_BUS_IS_PHYS (1) - -/* This is always fine. */ -#define pci_dac_dma_supported(pci_dev, mask) (0) - /* Return the index of the PCI controller for device. */ static inline int pci_controller_num(struct pci_dev *dev) { -- GitLab From 654b75e044119bf8e7d773bce41ea039281bbfbe Mon Sep 17 00:00:00 2001 From: Yu Zhao <yu.zhao@intel.com> Date: Fri, 26 Jun 2009 14:04:46 +0800 Subject: [PATCH 0375/1002] PCI: check if bus has a proper bridge device before triggering SBR For devices attached to the root bus, we can't trigger Secondary Bus Reset because there is no bridge device associated with the bus. So need to check bus->self again NULL first before using it. Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6c93af5ced186..d5d6f5667d831 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2171,7 +2171,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) u16 ctrl; struct pci_dev *pdev; - if (dev->subordinate) + if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) return -ENOTTY; list_for_each_entry(pdev, &dev->bus->devices, bus_list) -- GitLab From 503998ca4a295f7da233689850ba4b9d13cf41e7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <randy.dunlap@oracle.com> Date: Wed, 24 Jun 2009 09:18:14 -0700 Subject: [PATCH 0376/1002] PCI: fix kernel-doc warnings Add documentation for missing parameters in PCI hotplug code. Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/hotplug/pci_hotplug_core.c | 2 ++ drivers/pci/slot.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 844580489d4da..5c5043f239cf5 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name) * @slot: pointer to the &struct hotplug_slot to register * @devnr: device number * @name: name registered with kobject core + * @owner: caller module owner + * @mod_name: caller module name * * Registers a hotplug slot with the pci hotplug subsystem, which will allow * userspace interaction to the slot. diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index eddb0748b0ea3..8c02b6c53bdbd 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot); #include <linux/pci_hotplug.h> /** * pci_hp_create_link - create symbolic link to the hotplug driver module. - * @slot: struct pci_slot + * @pci_slot: struct pci_slot * * Helper function for pci_hotplug_core.c to create symbolic link to * the hotplug driver module. @@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link); /** * pci_hp_remove_link - remove symbolic link to the hotplug driver module. - * @slot: struct pci_slot + * @pci_slot: struct pci_slot * * Helper function for pci_hotplug_core.c to remove symbolic link to * the hotplug driver module. -- GitLab From 7a661c6f1082693a7e9627e9ad2d1546a9337fdc Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Wed, 24 Jun 2009 16:02:27 +0100 Subject: [PATCH 0377/1002] PCI: More PATA quirks for not entering D3 The ALi loses some state if it goes into D3. Unfortunately even with the chipset documents I can't figure out how to restore some bits of it. The VIA one saves/restores apparently fine but the ACPI _GTM methods break on some platforms if we do this and this causes cable misdetections. These are both effectively regressions as historically nothing matched the devices and then decided not to bind to them. Nowdays something is binding to all sorts of devices and a result they get dumped into D3. Signed-off-by: Alan Cox <alan@linux.intel.com> Acked-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/quirks.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 56552d74abea1..06b9656239623 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); +/* ALi loses some register settings that we cannot then restore */ +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3); +/* VIA comes back fine but we need to keep it alive or ACPI GTM failures + occur when mode detecting */ +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3); /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. -- GitLab From 2fc90f6133a87da8177636866557d4cc5f56e661 Mon Sep 17 00:00:00 2001 From: Alexey Zaytsev <zaytsev@altell.ru> Date: Wed, 24 Jun 2009 16:22:30 +0400 Subject: [PATCH 0378/1002] PCI: make pci_name() take const argument Since this function should never modify it (saves warnings when called with const args too). Signed-off-by: Alexey Zaytsev <zaytsev@altell.ru> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- include/linux/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index d304ddf412d06..115fb7ba50890 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1145,7 +1145,7 @@ static inline void pci_set_drvdata(struct pci_dev *pdev, void *data) /* If you want to know what to call your pci_dev, ask this function. * Again, it's a wrapper around the generic device. */ -static inline const char *pci_name(struct pci_dev *pdev) +static inline const char *pci_name(const struct pci_dev *pdev) { return dev_name(&pdev->dev); } -- GitLab From 2c21fd4b333e4c780a46edcd6d1e85bfc6cdf371 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Tue, 23 Jun 2009 17:40:04 +0900 Subject: [PATCH 0379/1002] PCI MSI: shorten PCI_MSIX_ENTRY_* symbol names These names are too long! Drop _OFFSET to save some bytes/lines. Reviewed-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/msi.c | 18 ++++++++---------- drivers/pci/msi.h | 10 +++++----- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 628c14150d49f..a088fc6f58388 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -151,7 +151,7 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag) { u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; + PCI_MSIX_ENTRY_VECTOR_CTRL; mask_bits &= ~1; mask_bits |= flag; writel(mask_bits, desc->mask_base + offset); @@ -188,9 +188,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) void __iomem *base = entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; - msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); + msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); + msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); + msg->data = readl(base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; int pos = entry->msi_attrib.pos; @@ -225,11 +225,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) base = entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; - writel(msg->address_lo, - base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(msg->address_hi, - base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); + writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); + writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); + writel(msg->data, base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; int pos = entry->msi_attrib.pos; @@ -493,7 +491,7 @@ static int msix_capability_init(struct pci_dev *dev, set_irq_msi(entry->irq, entry); j = entries[i].entry; entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); + PCI_MSIX_ENTRY_VECTOR_CTRL); msix_mask_irq(entry, 1); i++; } diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index a0662842550bc..de27c1cb5a2bb 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,11 +6,11 @@ #ifndef MSI_H #define MSI_H -#define PCI_MSIX_ENTRY_SIZE 16 -#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 -#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 -#define PCI_MSIX_ENTRY_DATA_OFFSET 8 -#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 #define msi_control_reg(base) (base + PCI_MSI_FLAGS) #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) -- GitLab From 7ba1930db02fc3118165338ef4e562869f575583 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Tue, 23 Jun 2009 17:39:27 +0900 Subject: [PATCH 0380/1002] PCI MSI: Unmask MSI if setup failed The initial state of mask register of MSI is unmasked. We set it masked before calling arch_setup_msi_irqs(). If arch_setup_msi_irq() fails, it is better to restore the state of the mask register. Reviewed-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/msi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a088fc6f58388..9ab4fe8f20af2 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -383,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) /* Configure MSI capability structure */ ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); if (ret) { + msi_mask_irq(entry, mask, ~mask); msi_free_irqs(dev); return ret; } -- GitLab From 12abb8ba8444f7c9b355bbdd44a6d0839f7a41b6 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Date: Wed, 24 Jun 2009 12:08:09 +0900 Subject: [PATCH 0381/1002] PCI MSI: Fix restoration of MSI/MSI-X mask states in suspend/resume There are 2 problems on mask states in suspend/resume. [1]: It is better to restore the mask states of MSI/MSI-X to initial states (MSI is unmasked, MSI-X is masked) when we release the device. The pci_msi_shutdown() does the restoration of mask states for MSI, while the msi_free_irqs() does it for MSI-X. In other words, in the "disable" path both of MSI and MSI-X are handled, but in the "shutdown" path only MSI is handled. MSI: pci_disable_msi() => pci_msi_shutdown() [ mask states for MSI restored ] => msi_set_enable(dev, pos, 0); => msi_free_irqs() MSI-X: pci_disable_msix() => pci_msix_shutdown() => msix_set_enable(dev, 0); => msix_free_all_irqs => msi_free_irqs() [ mask states for MSI-X restored ] This patch moves the masking for MSI-X from msi_free_irqs() to pci_msix_shutdown(). This change has some positive side effects: - It prevents OS from touching mask states before reading preserved bits in the register, which can be happen if msi_free_irqs() is called from error path in msix_capability_init(). - It also prevents touching the register after turning off MSI-X in "disable" path, which can be a problem on some devices. [2]: We have cache of the mask state in msi_desc, which is automatically updated when msi/msix_mask_irq() is called. This cached states are used for the resume. But since what need to be restored in the resume is the states before the shutdown on the suspend, calling msi/msix_mask_irq() from pci_msi/msix_shutdown() is not appropriate. This patch introduces __msi/msix_mask_irq() that do mask as same as msi/msix_mask_irq() but does not update cached state, for use in pci_msi/msix_shutdown(). [updated: get rid of msi/msix_mask_irq_nocache() (proposed by Matthew Wilcox)] Reviewed-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/msi.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9ab4fe8f20af2..d986afb7032bb 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control) * reliably as devices without an INTx disable bit will then generate a * level IRQ which will never be cleared. */ -static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) { u32 mask_bits = desc->masked; if (!desc->msi_attrib.maskbit) - return; + return 0; mask_bits &= ~mask; mask_bits |= flag; pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); - desc->masked = mask_bits; + + return mask_bits; +} + +static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +{ + desc->masked = __msi_mask_irq(desc, mask, flag); } /* @@ -147,7 +153,7 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) * file. This saves a few milliseconds when initialising devices with lots * of MSI-X interrupts. */ -static void msix_mask_irq(struct msi_desc *desc, u32 flag) +static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) { u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -155,7 +161,13 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag) mask_bits &= ~1; mask_bits |= flag; writel(mask_bits, desc->mask_base + offset); - desc->masked = mask_bits; + + return mask_bits; +} + +static void msix_mask_irq(struct msi_desc *desc, u32 flag) +{ + desc->masked = __msix_mask_irq(desc, flag); } static void msi_set_mask_bit(unsigned irq, u32 flag) @@ -616,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev) pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; + /* Return the device with MSI unmasked as initial states */ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); mask = msi_capable_mask(ctrl); - msi_mask_irq(desc, mask, ~mask); + /* Keep cached state to be restored */ + __msi_mask_irq(desc, mask, ~mask); /* Restore dev->irq to its default pin-assertion irq */ dev->irq = desc->msi_attrib.default_irq; @@ -658,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev) list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { if (entry->msi_attrib.is_msix) { - msix_mask_irq(entry, 1); if (list_is_last(&entry->list, &dev->msi_list)) iounmap(entry->mask_base); } @@ -746,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev) void pci_msix_shutdown(struct pci_dev* dev) { + struct msi_desc *entry; + if (!pci_msi_enable || !dev || !dev->msix_enabled) return; + /* Return the device with MSI-X masked as initial states */ + list_for_each_entry(entry, &dev->msi_list, list) { + /* Keep cached states to be restored */ + __msix_mask_irq(entry, 1); + } + msix_set_enable(dev, 0); pci_intx_for_msi(dev, 1); dev->msix_enabled = 0; -- GitLab From 210ad39fb7ef0bc0494483f517f42524f16bb2a7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Mon, 29 Jun 2009 21:50:54 +0200 Subject: [PATCH 0382/1002] perf stat: Use percentages for scaling output Peter expressed a strong preference for percentage based display of scaled values - so revert to that from the recently introduced multiplication-factor unit. Reported-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Jaswinder Singh Rajput <jaswinder@kernel.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3e5ea4e2e5fd9..c5a290727a92f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -307,7 +307,8 @@ static void print_counter(int counter) abs_printout(counter, count, noise); if (scaled) - fprintf(stderr, " (%7.2fx scaled)", (double)count[1]/count[2]); + fprintf(stderr, " (scaled from %.2f%%)", + (double) count[2] / count[1] * 100); fprintf(stderr, "\n"); } -- GitLab From 051ae7f7344f453616b6b10332d4d8e1d40ed823 Mon Sep 17 00:00:00 2001 From: Paul Mackerras <paulus@samba.org> Date: Mon, 29 Jun 2009 21:13:21 +1000 Subject: [PATCH 0383/1002] perf_counter tools: Reduce perf stat measurement overhead/skew Vince Weaver reported a 'perf stat' measurement overhead in the count of retired instructions, which can amount to a +6000 instructions inflated count in the reported count. At present, perf stat creates its counters on the perf process. Thus the counters count the fork and various other activity in both the parent and child, such as the resolver overhead for resolving PLT entries for any libc functions that haven't been called before, such as execvp. This reduces the overhead by creating the counters on the child process after the fork, using a couple of pipes to synchronize so that the child process waits until the parent has created the counters before doing the exec. To eliminate the PLT resolution overhead on calling execvp, this does a dummy execvp first which will always fail. With this, the overhead of executing a program goes down from over 4800 instructions to about 90 instructions on powerpc (32-bit). This was measured with a statically-linked program written in assembler which only does the 3 instructions needed to call _exit(0). Before: $ perf stat -e 0:1:u ./three Performance counter stats for './three': 4858 instructions 0.001274523 seconds time elapsed After: $ perf stat -e 0:1:u ./three Performance counter stats for './three': 92 instructions 0.000468153 seconds time elapsed Reported-by: Vince Weaver <vince@deater.net> Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <19016.41425.814043.870352@cargo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 64 ++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c5a290727a92f..201ef2367dcbf 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -99,7 +99,7 @@ static u64 runtime_cycles_noise; #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" -static void create_perf_stat_counter(int counter) +static void create_perf_stat_counter(int counter, int pid) { struct perf_counter_attr *attr = attrs + counter; @@ -119,7 +119,7 @@ static void create_perf_stat_counter(int counter) attr->inherit = inherit; attr->disabled = 1; - fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); + fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0); if (fd[0][counter] < 0 && verbose) fprintf(stderr, ERR_PERF_OPEN, counter, fd[0][counter], strerror(errno)); @@ -205,12 +205,58 @@ static int run_perf_stat(int argc, const char **argv) int status = 0; int counter; int pid; + int child_ready_pipe[2], go_pipe[2]; + char buf; if (!system_wide) nr_cpus = 1; + if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { + perror("failed to create pipes"); + exit(1); + } + + if ((pid = fork()) < 0) + perror("failed to fork"); + + if (!pid) { + close(child_ready_pipe[0]); + close(go_pipe[1]); + fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); + + /* + * Do a dummy execvp to get the PLT entry resolved, + * so we avoid the resolver overhead on the real + * execvp call. + */ + execvp("", (char **)argv); + + /* + * Tell the parent we're ready to go + */ + close(child_ready_pipe[1]); + + /* + * Wait until the parent tells us to go. + */ + read(go_pipe[0], &buf, 1); + + execvp(argv[0], (char **)argv); + + perror(argv[0]); + exit(-1); + } + + /* + * Wait for the child to be ready to exec. + */ + close(child_ready_pipe[1]); + close(go_pipe[0]); + read(child_ready_pipe[0], &buf, 1); + close(child_ready_pipe[0]); + for (counter = 0; counter < nr_counters; counter++) - create_perf_stat_counter(counter); + create_perf_stat_counter(counter, pid); /* * Enable counters and exec the command: @@ -218,19 +264,9 @@ static int run_perf_stat(int argc, const char **argv) t0 = rdclock(); prctl(PR_TASK_PERF_COUNTERS_ENABLE); - if ((pid = fork()) < 0) - perror("failed to fork"); - - if (!pid) { - if (execvp(argv[0], (char **)argv)) { - perror(argv[0]); - exit(-1); - } - } - + close(go_pipe[1]); wait(&status); - prctl(PR_TASK_PERF_COUNTERS_DISABLE); t1 = rdclock(); walltime_nsecs[run_idx] = t1 - t0; -- GitLab From 2bf427b25b79eb7cea27963a66c3d4684cae0e0c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Mon, 29 Jun 2009 19:20:42 -0700 Subject: [PATCH 0384/1002] ide: fix resume for CONFIG_BLK_DEV_IDEACPI=y commit 2f0d0fd2a605666d38e290c5c0d2907484352dc4 ("ide-acpi: cleanup do_drive_get_GTF()") didn't account for the lack of hwif->acpidata check in generic_ide_suspend() [ indirect user of do_drive_get_GTF() through ide_acpi_exec_tfs() ] resulting in broken resume when ACPI support is enabled but ACPI data is unavailable. Fix it by adding ide_port_acpi() helper for checking if port needs ACPI handling and cleaning generic_ide_{suspend,resume}() to use it instead of hiding hwif->acpidata and ide_noacpi checks in IDE ACPI helpers (this should help in preventing similar bugs in the future). While at it: - kill superfluous debugging printks in ide_acpi_{get,push}_timing() Reported-and-tested-by: Etienne Basset <etienne.basset@numericable.fr> Also-reported-and-tested-by: Jeff Chua <jeff.chua.linux@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-acpi.c | 37 +++++++------------------------------ drivers/ide/ide-pm.c | 30 ++++++++++++++++++------------ include/linux/ide.h | 2 ++ 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 77f79d26b2648..c509c9916464d 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -92,6 +92,11 @@ int ide_acpi_init(void) return 0; } +bool ide_port_acpi(ide_hwif_t *hwif) +{ + return ide_noacpi == 0 && hwif->acpidata; +} + /** * ide_get_dev_handle - finds acpi_handle and PCI device.function * @dev: device to locate @@ -352,9 +357,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive) unsigned long gtf_address; unsigned long obj_loc; - if (ide_noacpi) - return 0; - DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); @@ -389,16 +391,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) struct acpi_buffer output; union acpi_object *out_obj; - if (ide_noacpi) - return; - - DEBPRINT("ENTER:\n"); - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - return; - } - /* Setting up output buffer for _GTM */ output.length = ACPI_ALLOCATE_BUFFER; output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ @@ -479,16 +471,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif) struct ide_acpi_drive_link *master = &hwif->acpidata->master; struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; - if (ide_noacpi) - return; - - DEBPRINT("ENTER:\n"); - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - return; - } - /* Give the GTM buffer + drive Identify data to the channel via the * _STM method: */ /* setup input parameters buffer for _STM */ @@ -527,16 +509,11 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) ide_drive_t *drive; int i; - if (ide_noacpi || ide_noacpi_psx) + if (ide_noacpi_psx) return; DEBPRINT("ENTER:\n"); - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - return; - } - /* channel first and then drives for power on and verse versa for power off */ if (on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); @@ -616,7 +593,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) drive->name, err); } - if (!ide_acpionboot) { + if (ide_noacpi || ide_acpionboot == 0) { DEBPRINT("ACPI methods disabled on boot\n"); return; } diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index c14ca144cffe0..ad7be2669dcb9 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -10,9 +10,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) struct request_pm_state rqpm; int ret; - /* call ACPI _GTM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) - ide_acpi_get_timing(hwif); + if (ide_port_acpi(hwif)) { + /* call ACPI _GTM only once */ + if ((drive->dn & 1) == 0 || pair == NULL) + ide_acpi_get_timing(hwif); + } memset(&rqpm, 0, sizeof(rqpm)); rq = blk_get_request(drive->queue, READ, __GFP_WAIT); @@ -26,9 +28,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) ret = blk_execute_rq(drive->queue, NULL, rq, 0); blk_put_request(rq); - /* call ACPI _PS3 only after both devices are suspended */ - if (ret == 0 && ((drive->dn & 1) || pair == NULL)) - ide_acpi_set_state(hwif, 0); + if (ret == 0 && ide_port_acpi(hwif)) { + /* call ACPI _PS3 only after both devices are suspended */ + if ((drive->dn & 1) || pair == NULL) + ide_acpi_set_state(hwif, 0); + } return ret; } @@ -42,13 +46,15 @@ int generic_ide_resume(struct device *dev) struct request_pm_state rqpm; int err; - /* call ACPI _PS0 / _STM only once */ - if ((drive->dn & 1) == 0 || pair == NULL) { - ide_acpi_set_state(hwif, 1); - ide_acpi_push_timing(hwif); - } + if (ide_port_acpi(hwif)) { + /* call ACPI _PS0 / _STM only once */ + if ((drive->dn & 1) == 0 || pair == NULL) { + ide_acpi_set_state(hwif, 1); + ide_acpi_push_timing(hwif); + } - ide_acpi_exec_tfs(drive); + ide_acpi_exec_tfs(drive); + } memset(&rqpm, 0, sizeof(rqpm)); rq = blk_get_request(drive->queue, READ, __GFP_WAIT); diff --git a/include/linux/ide.h b/include/linux/ide.h index c6af7c44d46c8..edc93a6d931db 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1419,6 +1419,7 @@ static inline void ide_dma_unmap_sg(ide_drive_t *drive, #ifdef CONFIG_BLK_DEV_IDEACPI int ide_acpi_init(void); +bool ide_port_acpi(ide_hwif_t *hwif); extern int ide_acpi_exec_tfs(ide_drive_t *drive); extern void ide_acpi_get_timing(ide_hwif_t *hwif); extern void ide_acpi_push_timing(ide_hwif_t *hwif); @@ -1427,6 +1428,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *); extern void ide_acpi_set_state(ide_hwif_t *hwif, int on); #else static inline int ide_acpi_init(void) { return 0; } +static inline bool ide_port_acpi(ide_hwif_t *hwif) { return 0; } static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; } static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; } static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; } -- GitLab From e18ed145c7f556f1de8350c32739bf35b26df705 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer <christian.engelmayer@frequentis.com> Date: Mon, 29 Jun 2009 19:31:41 -0700 Subject: [PATCH 0385/1002] ide: memory overrun in ide_get_identity_ioctl() on big endian machines using ioctl HDIO_OBSOLETE_IDENTITY This patch fixes a memory overrun in function ide_get_identity_ioctl() which chooses the size of a memory buffer depending on the ioctl command that led to the function call, however, passes that buffer to a function which needs the buffer size to be always chosen unconditionally. Due to conditional compilation the memory overrun can only happen on big endian machines. The error can be triggered using ioctl HDIO_OBSOLETE_IDENTITY. Usage of ioctl HDIO_GET_IDENTITY is safe. Signed-off-by: Christian Engelmayer <christian.engelmayer@frequentis.com> Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/ide/ide-ioctls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 82f252c3ee6e5..e246d3d3fbcc5 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -64,7 +64,8 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, goto out; } - id = kmalloc(size, GFP_KERNEL); + /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */ + id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL); if (id == NULL) { rc = -ENOMEM; goto out; -- GitLab From 8e5b9dda99cc86bdbd822935fcc37c5808e271b3 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Sun, 28 Jun 2009 18:03:30 +0000 Subject: [PATCH 0386/1002] tcp: Stop non-TSO packets morphing into TSO If a socket starts out on a non-TSO route, and then switches to a TSO route, then the tail on the tx queue can morph into a TSO packet, causing mischief because the rest of the stack does not expect a partially linear TSO packet. This patch fixes this by ensuring that skb->ip_summed is set to CHECKSUM_PARTIAL before declaring a packet as TSO. Reported-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/tcp_output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 416fc4c2e7ebd..5bdf08d312d9b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -725,7 +725,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { - if (skb->len <= mss_now || !sk_can_gso(sk)) { + if (skb->len <= mss_now || !sk_can_gso(sk) || + skb->ip_summed == CHECKSUM_NONE) { /* Avoid the costly divide in the normal * non-TSO case. */ -- GitLab From 6828b92bd21acd65113dfe0541f19f5df0d9668f Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Sun, 28 Jun 2009 18:06:41 +0000 Subject: [PATCH 0387/1002] tcp: Do not tack on TSO data to non-TSO packet If a socket starts out on a non-TSO route, and then switches to a TSO route, then we will tack on data to the tail of the tx queue even if it started out life as non-TSO. This is suboptimal because all of it will then be copied and checksummed unnecessarily. This patch fixes this by ensuring that skb->ip_summed is set to CHECKSUM_PARTIAL before appending extra data beyond the MSS. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/tcp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 17b89c523f9d1..7870a535dac64 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -903,13 +903,17 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, iov++; while (seglen > 0) { - int copy; + int copy = 0; + int max = size_goal; skb = tcp_write_queue_tail(sk); + if (tcp_send_head(sk)) { + if (skb->ip_summed == CHECKSUM_NONE) + max = mss_now; + copy = max - skb->len; + } - if (!tcp_send_head(sk) || - (copy = size_goal - skb->len) <= 0) { - + if (copy <= 0) { new_segment: /* Allocate new segment. If the interface is SG, * allocate skb fitting to single page. @@ -930,6 +934,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, skb_entail(sk, skb); copy = size_goal; + max = size_goal; } /* Try to append data to the end of skb. */ @@ -1028,7 +1033,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, if ((seglen -= copy) == 0 && iovlen == 0) goto out; - if (skb->len < size_goal || (flags & MSG_OOB)) + if (skb->len < max || (flags & MSG_OOB)) continue; if (forced_push(tp)) { -- GitLab From 1802571b9865c0fc1d8d0fa39cf73275f3a75af3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Sun, 28 Jun 2009 18:42:53 +0000 Subject: [PATCH 0388/1002] xfrm: use xfrm_addr_cmp() instead of compare addresses directly Clean up to use xfrm_addr_cmp() instead of compare addresses directly. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/xfrm/xfrm_state.c | 57 ++++++------------------------------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5f1f86565f162..f2f7c638083e3 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -668,22 +668,10 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { if (x->props.family != family || x->id.spi != spi || - x->id.proto != proto) + x->id.proto != proto || + xfrm_addr_cmp(&x->id.daddr, daddr, family)) continue; - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)daddr, - (struct in6_addr *) - x->id.daddr.a6)) - continue; - break; - } - xfrm_state_hold(x); return x; } @@ -699,26 +687,11 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { if (x->props.family != family || - x->id.proto != proto) + x->id.proto != proto || + xfrm_addr_cmp(&x->id.daddr, daddr, family) || + xfrm_addr_cmp(&x->props.saddr, saddr, family)) continue; - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4 || - x->props.saddr.a4 != saddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)daddr, - (struct in6_addr *) - x->id.daddr.a6) || - !ipv6_addr_equal((struct in6_addr *)saddr, - (struct in6_addr *) - x->props.saddr.a6)) - continue; - break; - } - xfrm_state_hold(x); return x; } @@ -1001,25 +974,11 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family x->props.family != family || x->km.state != XFRM_STATE_ACQ || x->id.spi != 0 || - x->id.proto != proto) + x->id.proto != proto || + xfrm_addr_cmp(&x->id.daddr, daddr, family) || + xfrm_addr_cmp(&x->props.saddr, saddr, family)) continue; - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4 || - x->props.saddr.a4 != saddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6, - (struct in6_addr *)daddr) || - !ipv6_addr_equal((struct in6_addr *) - x->props.saddr.a6, - (struct in6_addr *)saddr)) - continue; - break; - } - xfrm_state_hold(x); return x; } -- GitLab From d51e9b0d94336db56a13fdc65bb30751e3ea33b7 Mon Sep 17 00:00:00 2001 From: Graf Yang <graf.yang@analog.com> Date: Mon, 29 Jun 2009 09:34:20 +0000 Subject: [PATCH 0389/1002] net/irda: convert bfin_sir to net_device_ops Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/irda/bfin_sir.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index f3eed6a8fba5e..911c082cee5ac 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -677,6 +677,14 @@ static int bfin_sir_init_iobuf(iobuff_t *io, int size) return 0; } +static const struct net_device_ops bfin_sir_ndo = { + .ndo_open = bfin_sir_open, + .ndo_stop = bfin_sir_stop, + .ndo_start_xmit = bfin_sir_hard_xmit, + .ndo_do_ioctl = bfin_sir_ioctl, + .ndo_get_stats = bfin_sir_stats, +}; + static int __devinit bfin_sir_probe(struct platform_device *pdev) { struct net_device *dev; @@ -718,12 +726,8 @@ static int __devinit bfin_sir_probe(struct platform_device *pdev) if (err) goto err_mem_3; - dev->hard_start_xmit = bfin_sir_hard_xmit; - dev->open = bfin_sir_open; - dev->stop = bfin_sir_stop; - dev->do_ioctl = bfin_sir_ioctl; - dev->get_stats = bfin_sir_stats; - dev->irq = sir_port->irq; + dev->netdev_ops = &bfin_sir_ndo; + dev->irq = sir_port->irq; irda_init_max_qos_capabilies(&self->qos); -- GitLab From ff0ac74afb5b9916641723a78796d4ee7937c2ea Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Sun, 28 Jun 2009 22:49:37 +0000 Subject: [PATCH 0390/1002] sctp: xmit sctp packet always return no route error Commit 'net: skb->dst accessors'(adf30907d63893e4208dfe3f5c88ae12bc2f25d5) broken the sctp protocol stack, the sctp packet can never be sent out after Eric Dumazet's patch, which have typo in the sctp code. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Acked-by: Vlad Yasevich <vladisalv.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/sctp/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index b764114445156..b94c211905666 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -407,7 +407,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) } dst = dst_clone(tp->dst); skb_dst_set(nskb, dst); - if (dst) + if (!dst) goto no_route; /* Build the SCTP header. */ -- GitLab From e1605495c716ef4eebdb7606bcd1b593f28e2837 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Mon, 29 Jun 2009 11:17:38 +0100 Subject: [PATCH 0391/1002] intel-iommu: Introduce domain_sg_mapping() to speed up intel_map_sg() Instead of calling domain_pfn_mapping() repeatedly with single or small numbers of pages, just pass the sglist in. It can optimise the number of cache flushes like domain_pfn_mapping() does, and gives a huge speedup for large scatterlists. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 83 +++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 11a23201445a4..28bd5f2d78fc9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1635,6 +1635,56 @@ static int domain_context_mapped(struct pci_dev *pdev) tmp->devfn); } +static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + struct scatterlist *sg, unsigned long nr_pages, + int prot) +{ + struct dma_pte *first_pte = NULL, *pte = NULL; + uint64_t pteval; + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; + unsigned long sg_res = 0; + + BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); + + if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) + return -EINVAL; + + prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + + while (nr_pages--) { + if (!sg_res) { + sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; + sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; + sg->dma_length = sg->length; + pteval = page_to_phys(sg_page(sg)) | prot; + } + if (!pte) { + first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); + if (!pte) + return -ENOMEM; + } + /* We don't need lock here, nobody else + * touches the iova range + */ + BUG_ON(dma_pte_addr(pte)); + pte->val = pteval; + pte++; + if (!nr_pages || + (unsigned long)pte >> VTD_PAGE_SHIFT != + (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + domain_flush_cache(domain, first_pte, + (void *)pte - (void *)first_pte); + pte = NULL; + } + iov_pfn++; + pteval += VTD_PAGE_SIZE; + sg_res--; + if (!sg_res) + sg = sg_next(sg); + } + return 0; +} + static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, unsigned long phys_pfn, unsigned long nr_pages, int prot) @@ -2758,27 +2808,18 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne prot |= DMA_PTE_WRITE; start_vpfn = mm_to_dma_pfn(iova->pfn_lo); - offset_pfn = 0; - for_each_sg(sglist, sg, nelems, i) { - int nr_pages = aligned_nrpages(sg->offset, sg->length); - ret = domain_pfn_mapping(domain, start_vpfn + offset_pfn, - page_to_dma_pfn(sg_page(sg)), - nr_pages, prot); - if (ret) { - /* clear the page */ - dma_pte_clear_range(domain, start_vpfn, - start_vpfn + offset_pfn); - /* free page tables */ - dma_pte_free_pagetable(domain, start_vpfn, - start_vpfn + offset_pfn); - /* free iova */ - __free_iova(&domain->iovad, iova); - return 0; - } - sg->dma_address = ((dma_addr_t)(start_vpfn + offset_pfn) - << VTD_PAGE_SHIFT) + sg->offset; - sg->dma_length = sg->length; - offset_pfn += nr_pages; + + ret = domain_sg_mapping(domain, start_vpfn, sglist, mm_to_dma_pfn(size), prot); + if (unlikely(ret)) { + /* clear the page */ + dma_pte_clear_range(domain, start_vpfn, + start_vpfn + size - 1); + /* free page tables */ + dma_pte_free_pagetable(domain, start_vpfn, + start_vpfn + size - 1); + /* free iova */ + __free_iova(&domain->iovad, iova); + return 0; } /* it's a non-present to present mapping. Only flush if caching mode */ -- GitLab From 9051aa0268dc1c3e42cd79a802b0af1f2bfcadae Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Mon, 29 Jun 2009 12:30:54 +0100 Subject: [PATCH 0392/1002] intel-iommu: Combine domain_pfn_mapping() and domain_sg_mapping() Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 62 ++++++++++++++------------------------- 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 28bd5f2d78fc9..14308533b1cb8 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1635,14 +1635,14 @@ static int domain_context_mapped(struct pci_dev *pdev) tmp->devfn); } -static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, - struct scatterlist *sg, unsigned long nr_pages, - int prot) +static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + struct scatterlist *sg, unsigned long phys_pfn, + unsigned long nr_pages, int prot) { struct dma_pte *first_pte = NULL, *pte = NULL; - uint64_t pteval; + phys_addr_t uninitialized_var(pteval); int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - unsigned long sg_res = 0; + unsigned long sg_res; BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); @@ -1651,6 +1651,13 @@ static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + if (sg) + sg_res = 0; + else { + sg_res = nr_pages + 1; + pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; + } + while (nr_pages--) { if (!sg_res) { sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; @@ -1685,43 +1692,18 @@ static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, return 0; } -static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, - unsigned long phys_pfn, unsigned long nr_pages, - int prot) +static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + struct scatterlist *sg, unsigned long nr_pages, + int prot) { - struct dma_pte *first_pte = NULL, *pte = NULL; - int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - - BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); - - if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) - return -EINVAL; - - prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); +} - while (nr_pages--) { - if (!pte) { - first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); - if (!pte) - return -ENOMEM; - } - /* We don't need lock here, nobody else - * touches the iova range - */ - BUG_ON(dma_pte_addr(pte)); - pte->val = (phys_pfn << VTD_PAGE_SHIFT) | prot; - pte++; - if (!nr_pages || - (unsigned long)pte >> VTD_PAGE_SHIFT != - (unsigned long)first_pte >> VTD_PAGE_SHIFT) { - domain_flush_cache(domain, first_pte, - (void *)pte - (void *)first_pte); - pte = NULL; - } - iov_pfn++; - phys_pfn++; - } - return 0; +static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + unsigned long phys_pfn, unsigned long nr_pages, + int prot) +{ + return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); } static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) -- GitLab From 1bf20f0dc5629032ddd07617139d9fbca66c1642 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Mon, 29 Jun 2009 22:06:43 +0100 Subject: [PATCH 0393/1002] intel-iommu: dump mappings but don't die on pte already set Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 14308533b1cb8..40ce5a03f18f2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1673,7 +1673,16 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, /* We don't need lock here, nobody else * touches the iova range */ - BUG_ON(dma_pte_addr(pte)); + if (unlikely(dma_pte_addr(pte))) { + static int dumps = 5; + printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx)\n", + iov_pfn, pte->val); + if (dumps) { + dumps--; + debug_dma_dump_mappings(NULL); + } + WARN_ON(1); + } pte->val = pteval; pte++; if (!nr_pages || -- GitLab From 3d7b0e4154b4963d6bd39991ec8eaa09caeb3994 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Tue, 30 Jun 2009 03:38:09 +0100 Subject: [PATCH 0394/1002] intel-iommu: Don't free too much in dma_pte_free_pagetable() The loop condition was wrong -- we should free a PMD only if its _entire_ range is within the range we're intending to clear. The early-termination condition was right, but not the loop. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 40ce5a03f18f2..35bdd2a06caae 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -815,7 +815,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, if (tmp + level_size(level) - 1 > last_pfn) return; - while (tmp <= last_pfn) { + while (tmp + level_size(level) - 1 <= last_pfn) { pte = dma_pfn_level_pte(domain, tmp, level); if (pte) { free_pgtable_page( -- GitLab From f3a0a52fff4dbfdea2dccc908d00c038481d888e Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Tue, 30 Jun 2009 03:40:07 +0100 Subject: [PATCH 0395/1002] intel-iommu: Performance improvement for dma_pte_free_pagetable() As with other functions, batch the CPU data cache flushes and don't keep recalculating PTE addresses. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 35bdd2a06caae..ec7e032d5ab50 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -797,7 +797,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, unsigned long last_pfn) { int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - struct dma_pte *pte; + struct dma_pte *first_pte, *pte; int total = agaw_to_level(domain->agaw); int level; unsigned long tmp; @@ -805,25 +805,32 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); - /* we don't need lock here, nobody else touches the iova range */ + /* We don't need lock here; nobody else touches the iova range */ level = 2; while (level <= total) { tmp = align_to_level(start_pfn, level); - /* Only clear this pte/pmd if we're asked to clear its - _whole_ range */ + /* If we can't even clear one PTE at this level, we're done */ if (tmp + level_size(level) - 1 > last_pfn) return; while (tmp + level_size(level) - 1 <= last_pfn) { - pte = dma_pfn_level_pte(domain, tmp, level); - if (pte) { - free_pgtable_page( - phys_to_virt(dma_pte_addr(pte))); + first_pte = pte = dma_pfn_level_pte(domain, tmp, level); + if (!pte) { + tmp = align_to_level(tmp + 1, level + 1); + continue; + } + while (tmp + level_size(level) - 1 <= last_pfn && + (unsigned long)pte >> VTD_PAGE_SHIFT == + (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); dma_clear_pte(pte); - domain_flush_cache(domain, pte, sizeof(*pte)); + pte++; + tmp += level_size(level); } - tmp += level_size(level); + domain_flush_cache(domain, first_pte, + (void *)pte - (void *)first_pte); + } level++; } -- GitLab From 6a84c234da06a4ac0c1b4c819b83cf264674c2d8 Mon Sep 17 00:00:00 2001 From: Grant Likely <grant.likely@secretlab.ca> Date: Sun, 28 Jun 2009 01:41:52 -0600 Subject: [PATCH 0396/1002] ASoC: Fix typo in MPC5200 PSC AC97 driver Kconfig ALSA SoC drivers should be specify SND_SOC_AC97_BUS instead, not AC97_BUS. Without SND_SOC_AC97_BUS defined, an AC97 device will not get correctly registered on the AC97 bus, which prevents thinks like the WM9712 touchscreen driver from getting probed. Tested against 2.6.31-rc1. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jon Smirl <jonsmirl@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/fsl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 5dbebf82249ca..5661876ee837a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -33,7 +33,7 @@ config SND_SOC_MPC5200_I2S config SND_SOC_MPC5200_AC97 tristate "Freescale MPC5200 PSC in AC97 mode driver" depends on PPC_MPC52xx && PPC_BESTCOMM - select AC97_BUS + select SND_SOC_AC97_BUS select SND_MPC52xx_DMA select PPC_BESTCOMM_GEN_BD help -- GitLab From 40d9ec14e7e1f62d2379ecc1b5ee00ddfc2a5d0c Mon Sep 17 00:00:00 2001 From: Grant Likely <grant.likely@secretlab.ca> Date: Sun, 28 Jun 2009 01:42:06 -0600 Subject: [PATCH 0397/1002] ASoC: remove BROKEN from Efika and pcm030 fabric drivers The needed spin_event_timeout() macro is now merged in from the powerpc tree, so these drivers are no longer broken. This reverts commit 0c0e09e21a9e7bc6ca54e06ef3d497255ca26383 (ASoC: Mark MPC5200 AC97 as BROKEN until PowerPC merge issues are resolved) Tested against 2.6.31-rc1. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jon Smirl <jonsmirl@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/fsl/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 5661876ee837a..8cb65ccad35fb 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -41,7 +41,7 @@ config SND_SOC_MPC5200_AC97 config SND_MPC52xx_SOC_PCM030 tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712" - depends on PPC_MPC5200_SIMPLE && BROKEN + depends on PPC_MPC5200_SIMPLE select SND_SOC_MPC5200_AC97 select SND_SOC_WM9712 help @@ -50,7 +50,7 @@ config SND_MPC52xx_SOC_PCM030 config SND_MPC52xx_SOC_EFIKA tristate "SoC AC97 Audio support for bbplan Efika and STAC9766" - depends on PPC_EFIKA && BROKEN + depends on PPC_EFIKA select SND_SOC_MPC5200_AC97 select SND_SOC_STAC9766 help -- GitLab From 1bdd7419910c1506151e7b9e2d60c6980e015f76 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Date: Sun, 28 Jun 2009 00:21:05 +0200 Subject: [PATCH 0398/1002] ASoC: OMAP: fix OMAP1510 broken PCM pointer callback This patch tries to work around the problem of broken OMAP1510 PCM playback pointer calculation by replacing DMA function call that incorrectly tries to read the value form DMA hardware with a value computed locally from an already maintained variable omap_runtime_data.period_index. Tested on OMAP5910 based Amstrad Delta (E3) using work in progress ASoC driver. Based on linux-2.6-asoc.git v2.6.31-rc1. Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/omap/omap-pcm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 6454e15f7d28c..84a1950880ebc 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -216,12 +216,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) dma_addr_t ptr; snd_pcm_uframes_t offset; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ptr = omap_get_dma_src_pos(prtd->dma_ch); - else + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ptr = omap_get_dma_dst_pos(prtd->dma_ch); + offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); + } else if (!(cpu_is_omap1510())) { + ptr = omap_get_dma_src_pos(prtd->dma_ch); + offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); + } else + offset = prtd->period_index * runtime->period_size; - offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); if (offset >= runtime->buffer_size) offset = 0; -- GitLab From 57e7986ed142417498155ebcd5eaf617ac37136d Mon Sep 17 00:00:00 2001 From: Paul Mackerras <paulus@samba.org> Date: Tue, 30 Jun 2009 16:07:19 +1000 Subject: [PATCH 0399/1002] perf_counter: Provide a way to enable counters on exec This provides a way to mark a counter to be enabled on the next exec. This is useful for measuring the total activity of a program without including overhead from the process that launches it. This also changes the perf stat command to use this new facility. Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <19017.43927.838745.689203@cargo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- include/linux/perf_counter.h | 3 ++- kernel/perf_counter.c | 50 ++++++++++++++++++++++++++++++++++++ tools/perf/builtin-stat.c | 6 ++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 3078e23c91ebd..5e970c7d3fd5b 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -179,8 +179,9 @@ struct perf_counter_attr { comm : 1, /* include comm data */ freq : 1, /* use freq, not period */ inherit_stat : 1, /* per task counts */ + enable_on_exec : 1, /* next exec enables */ - __reserved_1 : 52; + __reserved_1 : 51; __u32 wakeup_events; /* wakeup every n events */ __u32 __reserved_2; diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 66ab1e9d12946..d55a50da2347f 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1428,6 +1428,53 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu) perf_counter_task_sched_in(curr, cpu); } +/* + * Enable all of a task's counters that have been marked enable-on-exec. + * This expects task == current. + */ +static void perf_counter_enable_on_exec(struct task_struct *task) +{ + struct perf_counter_context *ctx; + struct perf_counter *counter; + unsigned long flags; + int enabled = 0; + + local_irq_save(flags); + ctx = task->perf_counter_ctxp; + if (!ctx || !ctx->nr_counters) + goto out; + + __perf_counter_task_sched_out(ctx); + + spin_lock(&ctx->lock); + + list_for_each_entry(counter, &ctx->counter_list, list_entry) { + if (!counter->attr.enable_on_exec) + continue; + counter->attr.enable_on_exec = 0; + if (counter->state >= PERF_COUNTER_STATE_INACTIVE) + continue; + counter->state = PERF_COUNTER_STATE_INACTIVE; + counter->tstamp_enabled = + ctx->time - counter->total_time_enabled; + enabled = 1; + } + + /* + * Unclone this context if we enabled any counter. + */ + if (enabled && ctx->parent_ctx) { + put_ctx(ctx->parent_ctx); + ctx->parent_ctx = NULL; + } + + spin_unlock(&ctx->lock); + + perf_counter_task_sched_in(task, smp_processor_id()); + out: + local_irq_restore(flags); +} + /* * Cross CPU call to read the hardware counter */ @@ -2949,6 +2996,9 @@ void perf_counter_comm(struct task_struct *task) { struct perf_comm_event comm_event; + if (task->perf_counter_ctxp) + perf_counter_enable_on_exec(task); + if (!atomic_read(&nr_comm_counters)) return; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 201ef2367dcbf..2e03524a1de0a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -116,8 +116,9 @@ static void create_perf_stat_counter(int counter, int pid) fd[cpu][counter], strerror(errno)); } } else { - attr->inherit = inherit; - attr->disabled = 1; + attr->inherit = inherit; + attr->disabled = 1; + attr->enable_on_exec = 1; fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0); if (fd[0][counter] < 0 && verbose) @@ -262,7 +263,6 @@ static int run_perf_stat(int argc, const char **argv) * Enable counters and exec the command: */ t0 = rdclock(); - prctl(PR_TASK_PERF_COUNTERS_ENABLE); close(go_pipe[1]); wait(&status); -- GitLab From 874d2f61d31e596c36af7732dc1b3aa2dc233824 Mon Sep 17 00:00:00 2001 From: Milan Broz <mbroz@redhat.com> Date: Tue, 30 Jun 2009 15:18:14 +0100 Subject: [PATCH 0400/1002] dm exception store: really fix type lookup Fix exception store name handling. We need to reference exception store by zero terminated string. Fixes regression introduced in commit f6bd4eb73cdf2a5bf954e497972842f39cabb7e3 Cc: Yi Yang <yi.y.yang@intel.com> Cc: Jonathan Brassow <jbrassow@redhat.com> Cc: stable@kernel.org Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> --- drivers/md/dm-exception-store.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index c3ae51584b12f..3710ff88fc101 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -195,7 +195,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, struct dm_exception_store **store) { int r = 0; - struct dm_exception_store_type *type; + struct dm_exception_store_type *type = NULL; struct dm_exception_store *tmp_store; char persistent; @@ -211,12 +211,15 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, } persistent = toupper(*argv[1]); - if (persistent != 'P' && persistent != 'N') { + if (persistent == 'P') + type = get_type("P"); + else if (persistent == 'N') + type = get_type("N"); + else { ti->error = "Persistent flag is not P or N"; return -EINVAL; } - type = get_type(&persistent); if (!type) { ti->error = "Exception store type not recognised"; r = -EINVAL; -- GitLab From ea9df47cc92573b159ef3b4fda516c32cba9c4fd Mon Sep 17 00:00:00 2001 From: Mike Snitzer <snitzer@redhat.com> Date: Tue, 30 Jun 2009 15:18:17 +0100 Subject: [PATCH 0401/1002] dm table: fix blk_stack_limits arg to use bytes not sectors The offset passed to blk_stack_limits() must be in bytes not sectors. Fixes false warnings like the following: device-mapper: table: 254:1: target device sda6 is misaligned Signed-off-by: Mike Snitzer <snitzer@redhat.com> Reported-by: Frans Pop <elendil@planet.nl> Tested-by: Frans Pop <elendil@planet.nl> Signed-off-by: Alasdair G Kergon <agk@redhat.com> --- drivers/md/dm-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4899ebe767c86..2cba557d9e61e 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -495,7 +495,7 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, return 0; } - if (blk_stack_limits(limits, &q->limits, start) < 0) + if (blk_stack_limits(limits, &q->limits, start << 9) < 0) DMWARN("%s: target device %s is misaligned", dm_device_name(ti->table->md), bdevname(bdev, b)); -- GitLab From f5812a7a336fb952d819e4427b9a2dce02368e82 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Tue, 30 Jun 2009 11:43:17 -0300 Subject: [PATCH 0402/1002] perf_counter tools: Adjust only prelinked symbol's addresses I.e. we can't handle these two kinds of files in the same way: 1) prelinked system library: [acme@doppio pahole]$ readelf -s /usr/lib64/libdw-0.141.so | egrep 'FUNC.+GLOBAL.+dwfl_report_elf' 278: 00000030450105a0 261 FUNC GLOBAL DEFAULT 12 dwfl_report_elf@@ELFUTILS_0.122 2) not prelinked library with debug information from a -debuginfo package: [acme@doppio pahole]$ readelf -s /usr/lib/debug/usr/lib64/libdw-0.141.so.debug | egrep 'FUNC.+GLOBAL.+dwfl_report_elf' 629: 00000000000105a0 261 FUNC GLOBAL DEFAULT 12 dwfl_report_elf [acme@doppio pahole]$ Now the numbers I got for a pahole perf run are in line with the numbers I get from oprofile. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20090630144317.GB12663@ghostprotocols.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/symbol.c | 16 +++++++++++----- tools/perf/util/symbol.h | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 9c659ef6aec2d..78c2efde01b7b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -520,7 +520,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); - + self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, + ".gnu.prelink_undo", + NULL) != NULL; elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { struct symbol *f; u64 obj_start; @@ -535,11 +537,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, gelf_getshdr(sec, &shdr); obj_start = sym.st_value; - if (verbose >= 2) - printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", - (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); + if (self->prelinked) { + if (verbose >= 2) + printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", + (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); - sym.st_value -= shdr.sh_addr - shdr.sh_offset; + sym.st_value -= shdr.sh_addr - shdr.sh_offset; + } f = symbol__new(sym.st_value, sym.st_size, elf_sym__name(&sym, symstrs), @@ -573,6 +577,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) if (!name) return -1; + self->prelinked = 0; + if (strncmp(self->name, "/tmp/perf-", 10) == 0) return dso__load_perf_map(self, filter, verbose); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 940b432db16ed..2c48ace8203bc 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -20,8 +20,9 @@ struct symbol { struct dso { struct list_head node; struct rb_root syms; - unsigned int sym_priv_size; struct symbol *(*find_symbol)(struct dso *, u64 ip); + unsigned int sym_priv_size; + unsigned char prelinked; char name[0]; }; -- GitLab From b4c458b3a23d76936e76678f2074b1528f129f7a Mon Sep 17 00:00:00 2001 From: Csaba Henk <csaba@gluster.com> Date: Mon, 29 Jun 2009 03:26:53 +0200 Subject: [PATCH 0403/1002] fuse: fix return value of fuse_dev_write() On 64 bit systems -- where sizeof(ssize_t) > sizeof(int) -- the following test exposes a bug due to a non-careful return of an int or unsigned value: implement a FUSE filesystem which sends an unsolicited notification to the kernel with invalid opcode. The respective write to /dev/fuse will return (1 << 32) - EINVAL with errno == 0 instead of -1 with errno == EINVAL. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> CC: stable@kernel.org --- fs/fuse/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8fed2ed12f38b..8a11a8c67c42c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -910,7 +910,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { int err; - unsigned nbytes = iov_length(iov, nr_segs); + size_t nbytes = iov_length(iov, nr_segs); struct fuse_req *req; struct fuse_out_header oh; struct fuse_copy_state cs; -- GitLab From 201fa69a2849536ef2912e8e971ec0b01c04eff4 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi <mszeredi@suse.cz> Date: Tue, 30 Jun 2009 20:06:24 +0200 Subject: [PATCH 0404/1002] fuse: fix bad return value in fuse_file_poll() Fix fuse_file_poll() which returned a -errno value instead of a poll mask. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> CC: stable@kernel.org --- fs/fuse/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fce6ce694fdee..cbc464043b6f0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1922,7 +1922,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) req = fuse_get_req(fc); if (IS_ERR(req)) - return PTR_ERR(req); + return POLLERR; req->in.h.opcode = FUSE_POLL; req->in.h.nodeid = ff->nodeid; -- GitLab From e0a43ddcc08c34dbd666d93600fd23914505f4aa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi <mszeredi@suse.cz> Date: Tue, 30 Jun 2009 20:12:23 +0200 Subject: [PATCH 0405/1002] fuse: allow umask processing in userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch lets filesystems handle masking the file mode on creation. This is needed if filesystem is using ACLs. - The CREATE, MKDIR and MKNOD requests are extended with a "umask" parameter. - A new FUSE_DONT_MASK flag is added to the INIT request/reply. With this the filesystem may request that the create mode is not masked. CC: Jean-Pierre André <jean-pierre.andre@wanadoo.fr> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> --- fs/fuse/dir.c | 20 +++++++++++++++++--- fs/fuse/fuse_i.h | 3 +++ fs/fuse/inode.c | 9 ++++++++- include/linux/fuse.h | 20 ++++++++++++++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index b3089a083d30c..6b700734e5197 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -375,7 +375,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_req *req; struct fuse_req *forget_req; - struct fuse_open_in inarg; + struct fuse_create_in inarg; struct fuse_open_out outopen; struct fuse_entry_out outentry; struct fuse_file *ff; @@ -399,15 +399,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, if (!ff) goto out_put_request; + if (!fc->dont_mask) + mode &= ~current_umask(); + flags &= ~O_NOCTTY; memset(&inarg, 0, sizeof(inarg)); memset(&outentry, 0, sizeof(outentry)); inarg.flags = flags; inarg.mode = mode; + inarg.umask = current_umask(); req->in.h.opcode = FUSE_CREATE; req->in.h.nodeid = get_node_id(dir); req->in.numargs = 2; - req->in.args[0].size = sizeof(inarg); + req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : + sizeof(inarg); req->in.args[0].value = &inarg; req->in.args[1].size = entry->d_name.len + 1; req->in.args[1].value = entry->d_name.name; @@ -546,12 +551,17 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, if (IS_ERR(req)) return PTR_ERR(req); + if (!fc->dont_mask) + mode &= ~current_umask(); + memset(&inarg, 0, sizeof(inarg)); inarg.mode = mode; inarg.rdev = new_encode_dev(rdev); + inarg.umask = current_umask(); req->in.h.opcode = FUSE_MKNOD; req->in.numargs = 2; - req->in.args[0].size = sizeof(inarg); + req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : + sizeof(inarg); req->in.args[0].value = &inarg; req->in.args[1].size = entry->d_name.len + 1; req->in.args[1].value = entry->d_name.name; @@ -578,8 +588,12 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) if (IS_ERR(req)) return PTR_ERR(req); + if (!fc->dont_mask) + mode &= ~current_umask(); + memset(&inarg, 0, sizeof(inarg)); inarg.mode = mode; + inarg.umask = current_umask(); req->in.h.opcode = FUSE_MKDIR; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index aaf2f9ff970ec..ede4f77b2d6c6 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -446,6 +446,9 @@ struct fuse_conn { /** Do multi-page cached writes */ unsigned big_writes:1; + /** Don't apply umask to creation modes */ + unsigned dont_mask:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d8673ccf90b75..6cc501bd01873 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -725,6 +725,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) } if (arg->flags & FUSE_BIG_WRITES) fc->big_writes = 1; + if (arg->flags & FUSE_DONT_MASK) + fc->dont_mask = 1; } else { ra_pages = fc->max_read / PAGE_CACHE_SIZE; fc->no_lock = 1; @@ -748,7 +750,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->minor = FUSE_KERNEL_MINOR_VERSION; arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | - FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES; + FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); @@ -864,6 +866,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (err) goto err_put_conn; + /* Handle umasking inside the fuse code */ + if (sb->s_flags & MS_POSIXACL) + fc->dont_mask = 1; + sb->s_flags |= MS_POSIXACL; + fc->release = fuse_free_conn; fc->flags = d.flags; fc->user_id = d.user_id; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index d41ed593f79fe..e2b816a624884 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -25,6 +25,9 @@ * - add IOCTL message * - add unsolicited notification support * - add POLL message and NOTIFY_POLL notification + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir */ #ifndef _LINUX_FUSE_H @@ -36,7 +39,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 11 +#define FUSE_KERNEL_MINOR_VERSION 12 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -112,6 +115,7 @@ struct fuse_file_lock { * INIT request/reply flags * * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_DONT_MASK: don't apply umask to file mode on create operations */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -119,6 +123,7 @@ struct fuse_file_lock { #define FUSE_ATOMIC_O_TRUNC (1 << 3) #define FUSE_EXPORT_SUPPORT (1 << 4) #define FUSE_BIG_WRITES (1 << 5) +#define FUSE_DONT_MASK (1 << 6) /** * CUSE INIT request/reply flags @@ -262,14 +267,18 @@ struct fuse_attr_out { struct fuse_attr attr; }; +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + struct fuse_mknod_in { __u32 mode; __u32 rdev; + __u32 umask; + __u32 padding; }; struct fuse_mkdir_in { __u32 mode; - __u32 padding; + __u32 umask; }; struct fuse_rename_in { @@ -300,8 +309,15 @@ struct fuse_setattr_in { }; struct fuse_open_in { + __u32 flags; + __u32 unused; +}; + +struct fuse_create_in { __u32 flags; __u32 mode; + __u32 umask; + __u32 padding; }; struct fuse_open_out { -- GitLab From 3b463ae0c6264f70e5d4c0a9c46af20fed43c96e Mon Sep 17 00:00:00 2001 From: John Muir <muirj@nortel.com> Date: Sun, 31 May 2009 11:13:57 -0400 Subject: [PATCH 0406/1002] fuse: invalidation reverse calls Add notification messages that allow the filesystem to invalidate VFS caches. Two notifications are added: 1) inode invalidation - invalidate cached attributes - invalidate a range of pages in the page cache (this is optional) 2) dentry invalidation - try to invalidate a subtree in the dentry cache Care must be taken while accessing the 'struct super_block' for the mount, as it can go away while an invalidation is in progress. To prevent this, introduce a rw-semaphore, that is taken for read during the invalidation and taken for write in the ->kill_sb callback. Cc: Csaba Henk <csaba@gluster.com> Cc: Anand Avati <avati@zresearch.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> --- fs/fuse/dev.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ fs/fuse/dir.c | 37 ++++++++++++++++++++ fs/fuse/fuse_i.h | 24 +++++++++++++ fs/fuse/inode.c | 59 ++++++++++++++++++++++++++++++-- include/linux/fuse.h | 16 +++++++++ 5 files changed, 214 insertions(+), 3 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8a11a8c67c42c..f58ecbc416c86 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -849,6 +849,81 @@ static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size, return err; } +static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, + struct fuse_copy_state *cs) +{ + struct fuse_notify_inval_inode_out outarg; + int err = -EINVAL; + + if (size != sizeof(outarg)) + goto err; + + err = fuse_copy_one(cs, &outarg, sizeof(outarg)); + if (err) + goto err; + fuse_copy_finish(cs); + + down_read(&fc->killsb); + err = -ENOENT; + if (!fc->sb) + goto err_unlock; + + err = fuse_reverse_inval_inode(fc->sb, outarg.ino, + outarg.off, outarg.len); + +err_unlock: + up_read(&fc->killsb); + return err; + +err: + fuse_copy_finish(cs); + return err; +} + +static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, + struct fuse_copy_state *cs) +{ + struct fuse_notify_inval_entry_out outarg; + int err = -EINVAL; + char buf[FUSE_NAME_MAX+1]; + struct qstr name; + + if (size < sizeof(outarg)) + goto err; + + err = fuse_copy_one(cs, &outarg, sizeof(outarg)); + if (err) + goto err; + + err = -ENAMETOOLONG; + if (outarg.namelen > FUSE_NAME_MAX) + goto err; + + name.name = buf; + name.len = outarg.namelen; + err = fuse_copy_one(cs, buf, outarg.namelen + 1); + if (err) + goto err; + fuse_copy_finish(cs); + buf[outarg.namelen] = 0; + name.hash = full_name_hash(name.name, name.len); + + down_read(&fc->killsb); + err = -ENOENT; + if (!fc->sb) + goto err_unlock; + + err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); + +err_unlock: + up_read(&fc->killsb); + return err; + +err: + fuse_copy_finish(cs); + return err; +} + static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, unsigned int size, struct fuse_copy_state *cs) { @@ -856,6 +931,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, case FUSE_NOTIFY_POLL: return fuse_notify_poll(fc, size, cs); + case FUSE_NOTIFY_INVAL_INODE: + return fuse_notify_inval_inode(fc, size, cs); + + case FUSE_NOTIFY_INVAL_ENTRY: + return fuse_notify_inval_entry(fc, size, cs); + default: fuse_copy_finish(cs); return -EINVAL; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 6b700734e5197..e703654e7f40d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -859,6 +859,43 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, return err; } +int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, + struct qstr *name) +{ + int err = -ENOTDIR; + struct inode *parent; + struct dentry *dir; + struct dentry *entry; + + parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); + if (!parent) + return -ENOENT; + + mutex_lock(&parent->i_mutex); + if (!S_ISDIR(parent->i_mode)) + goto unlock; + + err = -ENOENT; + dir = d_find_alias(parent); + if (!dir) + goto unlock; + + entry = d_lookup(dir, name); + dput(dir); + if (!entry) + goto unlock; + + fuse_invalidate_attr(parent); + fuse_invalidate_entry(entry); + dput(entry); + err = 0; + + unlock: + mutex_unlock(&parent->i_mutex); + iput(parent); + return err; +} + /* * Calling into a user-controlled filesystem gives the filesystem * daemon ptrace-like capabilities over the requester process. This diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index ede4f77b2d6c6..52b641fc0faf1 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -484,6 +484,12 @@ struct fuse_conn { /** Called on final put */ void (*release)(struct fuse_conn *); + + /** Super block for this connection. */ + struct super_block *sb; + + /** Read/write semaphore to hold when accessing sb. */ + struct rw_semaphore killsb; }; static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) @@ -511,6 +517,11 @@ extern const struct file_operations fuse_dev_operations; extern const struct dentry_operations fuse_dentry_operations; +/** + * Inode to nodeid comparison. + */ +int fuse_inode_eq(struct inode *inode, void *_nodeidp); + /** * Get a filled in inode */ @@ -711,6 +722,19 @@ void fuse_release_nowrite(struct inode *inode); u64 fuse_get_attr_version(struct fuse_conn *fc); +/** + * File-system tells the kernel to invalidate cache for the given node id. + */ +int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, + loff_t offset, loff_t len); + +/** + * File-system tells the kernel to invalidate parent attributes and + * the dentry matching parent/name. + */ +int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, + struct qstr *name); + int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, bool isdir); ssize_t fuse_direct_io(struct file *file, const char __user *buf, diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6cc501bd01873..f91ccc4a189de 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -206,7 +206,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) BUG(); } -static int fuse_inode_eq(struct inode *inode, void *_nodeidp) +int fuse_inode_eq(struct inode *inode, void *_nodeidp) { u64 nodeid = *(u64 *) _nodeidp; if (get_node_id(inode) == nodeid) @@ -257,6 +257,31 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, return inode; } +int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, + loff_t offset, loff_t len) +{ + struct inode *inode; + pgoff_t pg_start; + pgoff_t pg_end; + + inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); + if (!inode) + return -ENOENT; + + fuse_invalidate_attr(inode); + if (offset >= 0) { + pg_start = offset >> PAGE_CACHE_SHIFT; + if (len <= 0) + pg_end = -1; + else + pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT; + invalidate_inode_pages2_range(inode->i_mapping, + pg_start, pg_end); + } + iput(inode); + return 0; +} + static void fuse_umount_begin(struct super_block *sb) { fuse_abort_conn(get_fuse_conn_super(sb)); @@ -480,6 +505,7 @@ void fuse_conn_init(struct fuse_conn *fc) memset(fc, 0, sizeof(*fc)); spin_lock_init(&fc->lock); mutex_init(&fc->inst_mutex); + init_rwsem(&fc->killsb); atomic_set(&fc->count, 1); init_waitqueue_head(&fc->waitq); init_waitqueue_head(&fc->blocked_waitq); @@ -862,6 +888,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) fuse_conn_init(fc); fc->dev = sb->s_dev; + fc->sb = sb; err = fuse_bdi_init(fc, sb); if (err) goto err_put_conn; @@ -948,12 +975,25 @@ static int fuse_get_sb(struct file_system_type *fs_type, return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); } +static void fuse_kill_sb_anon(struct super_block *sb) +{ + struct fuse_conn *fc = get_fuse_conn_super(sb); + + if (fc) { + down_write(&fc->killsb); + fc->sb = NULL; + up_write(&fc->killsb); + } + + kill_anon_super(sb); +} + static struct file_system_type fuse_fs_type = { .owner = THIS_MODULE, .name = "fuse", .fs_flags = FS_HAS_SUBTYPE, .get_sb = fuse_get_sb, - .kill_sb = kill_anon_super, + .kill_sb = fuse_kill_sb_anon, }; #ifdef CONFIG_BLOCK @@ -965,11 +1005,24 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type, mnt); } +static void fuse_kill_sb_blk(struct super_block *sb) +{ + struct fuse_conn *fc = get_fuse_conn_super(sb); + + if (fc) { + down_write(&fc->killsb); + fc->sb = NULL; + up_write(&fc->killsb); + } + + kill_block_super(sb); +} + static struct file_system_type fuseblk_fs_type = { .owner = THIS_MODULE, .name = "fuseblk", .get_sb = fuse_get_sb_blk, - .kill_sb = kill_block_super, + .kill_sb = fuse_kill_sb_blk, .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, }; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index e2b816a624884..cf593bf9fd325 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -28,6 +28,8 @@ * * 7.12 * - add umask flag to input argument of open, mknod and mkdir + * - add notification messages for invalidation of inodes and + * directory entries */ #ifndef _LINUX_FUSE_H @@ -229,6 +231,8 @@ enum fuse_opcode { enum fuse_notify_code { FUSE_NOTIFY_POLL = 1, + FUSE_NOTIFY_INVAL_INODE = 2, + FUSE_NOTIFY_INVAL_ENTRY = 3, FUSE_NOTIFY_CODE_MAX, }; @@ -524,4 +528,16 @@ struct fuse_dirent { #define FUSE_DIRENT_SIZE(d) \ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) +struct fuse_notify_inval_inode_out { + __u64 ino; + __s64 off; + __s64 len; +}; + +struct fuse_notify_inval_entry_out { + __u64 parent; + __u32 namelen; + __u32 padding; +}; + #endif /* _LINUX_FUSE_H */ -- GitLab From 01e532981460594fffbf9b992ecfc96a78369924 Mon Sep 17 00:00:00 2001 From: Naohiro Ooiwa <nooiwa@miraclelinux.com> Date: Tue, 30 Jun 2009 12:44:19 -0700 Subject: [PATCH 0407/1002] bnx2x: Fix the behavior of ethtool when ONBOOT=no This is the same fix as commit 7959ea254ed18faee41160b1c50b3c9664735967 ("bnx2: Fix the behavior of ethtool when ONBOOT=no"), but for bnx2x: -------------------- When configure in ifcfg-eth* is ONBOOT=no, the behavior of ethtool command is wrong. # grep ONBOOT /etc/sysconfig/network-scripts/ifcfg-eth2 ONBOOT=no # ethtool eth2 | tail -n1 Link detected: yes I think "Link detected" should be "no". -------------------- Signed-off-by: Naohiro Ooiwa <nooiwa@miraclelinux.com> Acked-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/bnx2x_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fbf1352e9c1cb..951714a7f90a8 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -8637,6 +8637,14 @@ static int bnx2x_nway_reset(struct net_device *dev) return 0; } +static u32 +bnx2x_get_link(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + + return bp->link_vars.link_up; +} + static int bnx2x_get_eeprom_len(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); @@ -10034,7 +10042,7 @@ static struct ethtool_ops bnx2x_ethtool_ops = { .get_msglevel = bnx2x_get_msglevel, .set_msglevel = bnx2x_set_msglevel, .nway_reset = bnx2x_nway_reset, - .get_link = ethtool_op_get_link, + .get_link = bnx2x_get_link, .get_eeprom_len = bnx2x_get_eeprom_len, .get_eeprom = bnx2x_get_eeprom, .set_eeprom = bnx2x_set_eeprom, -- GitLab From 008440e3ad4b72f5048d1b1f6f5ed894fdc5ad08 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski <jarkao2@gmail.com> Date: Tue, 30 Jun 2009 12:47:19 -0700 Subject: [PATCH 0408/1002] ipv4: Fix fib_trie rebalancing, part 3 Alas current delaying of freeing old tnodes by RCU in trie_rebalance is still not enough because we can free a top tnode before updating a t->trie pointer. Reported-by: Pawel Staszewski <pstaszewski@itcare.pl> Tested-by: Pawel Staszewski <pstaszewski@itcare.pl> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/fib_trie.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 012cf5a685814..00a54b246dfed 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1021,6 +1021,9 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) (struct node *)tn, wasfull); tp = node_parent((struct node *) tn); + if (!tp) + rcu_assign_pointer(t->trie, (struct node *)tn); + tnode_free_flush(); if (!tp) break; -- GitLab From f7c2df9b55212d5ec94169a4de11e44c683e0af4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Tue, 30 Jun 2009 21:10:13 +0100 Subject: [PATCH 0409/1002] AFS: Fix lock imbalance Don't unlock on vfs_rejected_lock path in afs_do_setlk, since the lock is unlocked after abort_attempt label. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/afs/flock.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/afs/flock.c b/fs/afs/flock.c index 210acafe4a9b5..3ff8bdd18fb3b 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c @@ -432,7 +432,6 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl) list_del_init(&fl->fl_u.afs.link); if (list_empty(&vnode->granted_locks)) afs_defer_unlock(vnode, key); - spin_unlock(&vnode->lock); goto abort_attempt; } -- GitLab From 2cdb3f1d834aab27a927be7555fbf4f9e43e9261 Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Wed, 24 Jun 2009 19:01:19 -0700 Subject: [PATCH 0410/1002] x86/PCI: fix boundary checking when using root CRS Don't touch info->res_num if we are out of space. Acked-by: Gary Hade <garyhade@us.ibm.com> Tested-by: Gary Hade <garyhade@us.ibm.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- arch/x86/pci/acpi.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index b26626dc517c0..8bf152910eb02 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -68,6 +68,10 @@ setup_resource(struct acpi_resource *acpi_res, void *data) unsigned long flags; struct resource *root; int max_root_bus_resources = PCI_BUS_NUM_RESOURCES; + u64 start, end; + + if (bus_has_transparent_bridge(info->bus)) + max_root_bus_resources -= 3; status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) @@ -84,25 +88,24 @@ setup_resource(struct acpi_resource *acpi_res, void *data) } else return AE_OK; - res = &info->res[info->res_num]; - res->name = info->name; - res->flags = flags; - res->start = addr.minimum + addr.translation_offset; - res->end = res->start + addr.address_length - 1; - res->child = NULL; - - if (bus_has_transparent_bridge(info->bus)) - max_root_bus_resources -= 3; + start = addr.minimum + addr.translation_offset; + end = start + addr.address_length - 1; if (info->res_num >= max_root_bus_resources) { printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx " "from %s for %s due to _CRS returning more than " - "%d resource descriptors\n", (unsigned long) res->start, - (unsigned long) res->end, root->name, info->name, + "%d resource descriptors\n", (unsigned long) start, + (unsigned long) end, root->name, info->name, max_root_bus_resources); - info->res_num++; return AE_OK; } + res = &info->res[info->res_num]; + res->name = info->name; + res->flags = flags; + res->start = start; + res->end = end; + res->child = NULL; + if (insert_resource(root, res)) { printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " "from %s for %s\n", (unsigned long) res->start, -- GitLab From 626fdfec1588ac1341a37805809d03a719d977e0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Wed, 24 Jun 2009 20:00:12 -0700 Subject: [PATCH 0411/1002] x86/PCI: get root CRS before scanning children This allows us to remove adjust_transparent_bridge_resources and give x86_pci_root_bus_res_quirks a chance when _CRS is not used or not there. Acked-by: Gary Hade <garyhade@us.ibm.com> Tested-by: Gary Hade <garyhade@us.ibm.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- arch/x86/pci/acpi.c | 32 +++++++++----------------------- arch/x86/pci/amd_bus.c | 8 ++++++-- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 8bf152910eb02..1014eb4bfc37a 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -117,23 +117,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } -static void -adjust_transparent_bridge_resources(struct pci_bus *bus) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - int i; - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) { - for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) - dev->subordinate->resource[i] = - dev->bus->resource[i - 3]; - } - } -} - static void get_current_resources(struct acpi_device *device, int busnum, int domain, struct pci_bus *bus) @@ -161,8 +144,6 @@ get_current_resources(struct acpi_device *device, int busnum, info.res_num = 0; acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, &info); - if (info.res_num) - adjust_transparent_bridge_resources(bus); return; @@ -225,8 +206,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do */ memcpy(bus->sysdata, sd, sizeof(*sd)); kfree(sd); - } else - bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); + } else { + bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); + if (bus) { + if (pci_probe & PCI_USE__CRS) + get_current_resources(device, busnum, domain, + bus); + bus->subordinate = pci_scan_child_bus(bus); + } + } if (!bus) kfree(sd); @@ -241,8 +229,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do #endif } - if (bus && (pci_probe & PCI_USE__CRS)) - get_current_resources(device, busnum, domain, bus); return bus; } diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index f893d6a6e803e..3ffa10df20b9f 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -100,8 +100,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) int j; struct pci_root_info *info; - /* don't go for it if _CRS is used */ - if (pci_probe & PCI_USE__CRS) + /* don't go for it if _CRS is used already */ + if (b->resource[0] != &ioport_resource || + b->resource[1] != &iomem_resource) return; /* if only one root bus, don't need to anything */ @@ -116,6 +117,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b) if (i == pci_root_num) return; + printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", + b->number); + info = &pci_root_info[i]; for (j = 0; j < info->res_num; j++) { struct resource *res; -- GitLab From 2be8412c6cef97b01dfaae71c04bf585d3d93a3b Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Tue, 30 Jun 2009 14:02:00 -0700 Subject: [PATCH 0412/1002] [IA64] sprintf should not be used with same source & destination address This happens to work at the moment but isn't a good idea so fix it the simple way. Resolves-bug: http://bugzilla.kernel.org/show_bug.cgi?id=13576 Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> --- arch/ia64/sn/kernel/io_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 76645cf6ac5d1..25831c47c579b 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -435,7 +435,8 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address) bricktype = MODULE_GET_BTYPE(moduleid); if ((bricktype == L1_BRICKTYPE_191010) || (bricktype == L1_BRICKTYPE_1932)) - sprintf(address, "%s^%d", address, geo_slot(geoid)); + sprintf(address + strlen(address), "^%d", + geo_slot(geoid)); } void __devinit -- GitLab From 58782b34e9ffcc04619634efe9658263344ed188 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 09:26:07 -0700 Subject: [PATCH 0413/1002] [IA64] Remove unnecessary semicolons Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Tony Luck <tony.luck@intel.com> --- arch/ia64/kernel/esi.c | 2 +- arch/ia64/kvm/process.c | 6 +++--- arch/ia64/kvm/vcpu.c | 2 +- arch/ia64/kvm/vtlb.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c index ebf4e988e78ca..d5764a3d74af2 100644 --- a/arch/ia64/kernel/esi.c +++ b/arch/ia64/kernel/esi.c @@ -65,7 +65,7 @@ static int __init esi_init (void) } if (!esi) - return -ENODEV;; + return -ENODEV; systab = __va(esi); diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index a8f84da04b49b..bb862fb224f29 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -130,7 +130,7 @@ static void collect_interruption(struct kvm_vcpu *vcpu) if (vdcr & IA64_DCR_PP) { vpsr |= IA64_PSR_PP; } else { - vpsr &= ~IA64_PSR_PP;; + vpsr &= ~IA64_PSR_PP; } vcpu_set_psr(vcpu, vpsr); @@ -594,11 +594,11 @@ static void set_pal_call_data(struct kvm_vcpu *vcpu) p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30); break; case PAL_BRAND_INFO: - p->u.pal_data.gr29 = gr29;; + p->u.pal_data.gr29 = gr29; p->u.pal_data.gr30 = kvm_trans_pal_call_args(vcpu, gr30); break; default: - p->u.pal_data.gr29 = gr29;; + p->u.pal_data.gr29 = gr29; p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30); } p->u.pal_data.gr28 = gr28; diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c index a2c6c15e47618..46b02cbcc8748 100644 --- a/arch/ia64/kvm/vcpu.c +++ b/arch/ia64/kvm/vcpu.c @@ -406,7 +406,7 @@ void getreg(unsigned long regnum, unsigned long *val, * Now look at registers in [0-31] range and init correct UNAT */ addr = (unsigned long)regs; - unat = ®s->eml_unat;; + unat = ®s->eml_unat; addr += gr_info[regnum]; diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c index 4290a429bf7c9..20b3852f7a6ec 100644 --- a/arch/ia64/kvm/vtlb.c +++ b/arch/ia64/kvm/vtlb.c @@ -135,7 +135,7 @@ struct thash_data *__vtr_lookup(struct kvm_vcpu *vcpu, u64 va, int type) u64 rid; rid = vcpu_get_rr(vcpu, va); - rid = rid & RR_RID_MASK;; + rid = rid & RR_RID_MASK; if (type == D_TLB) { if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) { for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0; @@ -518,7 +518,7 @@ struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data) struct thash_cb *hcb = &v->arch.vtlb; - cch = __vtr_lookup(v, va, is_data);; + cch = __vtr_lookup(v, va, is_data); if (cch) return cch; -- GitLab From fa276f36f3d8743295e067fb483b42dca8bd1ece Mon Sep 17 00:00:00 2001 From: Jan Beulich <JBeulich@novell.com> Date: Tue, 30 Jun 2009 12:01:57 +0100 Subject: [PATCH 0414/1002] [IA64] address compiler warnings perfmon.c/salinfo.c perfmon.c has a dubious cast directly from "int" to "void *". Add an intermediate cast to "long" to keep gcc happy. salinfo.c uses "down_trylock()" in a highly creative way (explained in the comments in the file) ... but it does kick out this warning: arch/ia64/kernel/salinfo.c:195: warning: ignoring return value of 'down_trylock' which people occasionally try to "fix" in ways that do not work. Use some casts to keep gcc quiet. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Tony Luck <tony.luck@intel.com> --- arch/ia64/kernel/perfmon.c | 2 +- arch/ia64/kernel/salinfo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index abce2468a40ba..f1782705b1f72 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -5603,7 +5603,7 @@ pfm_interrupt_handler(int irq, void *arg) * /proc/perfmon interface, for debug only */ -#define PFM_PROC_SHOW_HEADER ((void *)nr_cpu_ids+1) +#define PFM_PROC_SHOW_HEADER ((void *)(long)nr_cpu_ids+1) static void * pfm_proc_start(struct seq_file *m, loff_t *pos) diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 7053c55b76493..e6676fca48287 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -192,7 +192,7 @@ struct salinfo_platform_oemdata_parms { static void salinfo_work_to_do(struct salinfo_data *data) { - down_trylock(&data->mutex); + (void)(down_trylock(&data->mutex) ?: 0); up(&data->mutex); } -- GitLab From fadfd2b6ba8838a6cc458dbae214993a177a3ee9 Mon Sep 17 00:00:00 2001 From: Tony Luck <tony.luck@intel.com> Date: Tue, 30 Jun 2009 14:28:54 -0700 Subject: [PATCH 0415/1002] Add Fenghua Yu as temporary co-maintainer for ia64 I'm taking my sabbatical from Intel for July/August 2009. Fenghua Yu will handle ia64 architecture while I'm gone. Signed-off-by: Tony Luck <tony.luck@intel.com> --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 05a9a563042f0..f3bbc759360c3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2851,7 +2851,9 @@ S: Maintained IA64 (Itanium) PLATFORM P: Tony Luck +P: Fenghua Yu M: tony.luck@intel.com +M: fenghua.yu@intel.com L: linux-ia64@vger.kernel.org W: http://www.ia64-linux.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git -- GitLab From 9e314996e3dc5189b9b36dce67088e882e989897 Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Tue, 30 Jun 2009 15:00:20 +0200 Subject: [PATCH 0416/1002] x86: Fix symbol annotation for arch/x86/lib/clear_page_64.S::clear_page_c Noticed the zero-sized function symbol while looking at 'perf' profiles, it causes the profiler to display those addresses in hexa. Turns out that this was wrong/bogus for an eternity. Signed-off-by: Mike Galbraith <efault@gmx.de> Acked-by: Alexander van Heukelum <heukelum@fastmail.fm> Acked-by: Cyrill Gorcunov <gorcunov@gmail.com> LKML-Reference: <1246366820.6538.1.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/clear_page_64.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index 9a10a78bb4a41..ebeafcce04a9b 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -5,15 +5,14 @@ * Zero a page. * rdi page */ - ALIGN -clear_page_c: +ENTRY(clear_page_c) CFI_STARTPROC movl $4096/8,%ecx xorl %eax,%eax rep stosq ret CFI_ENDPROC -ENDPROC(clear_page) +ENDPROC(clear_page_c) ENTRY(clear_page) CFI_STARTPROC -- GitLab From 25903407da21552419e0955705d6d8c8e601cb2e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Tue, 30 Jun 2009 19:01:20 -0300 Subject: [PATCH 0417/1002] perf report: Add --dsos parameter So that we can filter by dso. Symbols in other dsos won't be accounted for. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246399282-20934-2-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Documentation/perf-report.txt | 4 + tools/perf/Makefile | 2 + tools/perf/builtin-report.c | 16 ++ tools/perf/util/strlist.c | 184 +++++++++++++++++++++++ tools/perf/util/strlist.h | 32 ++++ 5 files changed, 238 insertions(+) create mode 100644 tools/perf/util/strlist.c create mode 100644 tools/perf/util/strlist.h diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 40c1db83a16da..13d85ca8c914e 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -20,6 +20,10 @@ OPTIONS -i:: --input=:: Input file name. (default: perf.data) +-d:: +--dsos=:: + Only consider symbols in these dsos. CSV that understands + file://filename entries. SEE ALSO -------- diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 1c1296d8a64bd..9c6d0ae3708e0 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -301,6 +301,7 @@ LIB_H += util/util.h LIB_H += util/help.h LIB_H += util/strbuf.h LIB_H += util/string.h +LIB_H += util/strlist.h LIB_H += util/run-command.h LIB_H += util/sigchain.h LIB_H += util/symbol.h @@ -322,6 +323,7 @@ LIB_OBJS += util/run-command.o LIB_OBJS += util/quote.o LIB_OBJS += util/strbuf.o LIB_OBJS += util/string.o +LIB_OBJS += util/strlist.o LIB_OBJS += util/usage.o LIB_OBJS += util/wrapper.o LIB_OBJS += util/sigchain.o diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ed391db9e0f8d..7c6b6e776718b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -16,6 +16,7 @@ #include "util/symbol.h" #include "util/string.h" #include "util/callchain.h" +#include "util/strlist.h" #include "perf.h" #include "util/header.h" @@ -32,6 +33,8 @@ static char *vmlinux = NULL; static char default_sort_order[] = "comm,dso"; static char *sort_order = default_sort_order; +static char *dso_list_str; +static struct strlist *dso_list; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; @@ -1272,6 +1275,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if (show & show_mask) { struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); + if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name)) + return 0; + if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { eprintf("problem incrementing symbol count, skipping event\n"); return -1; @@ -1659,6 +1665,8 @@ static const struct option options[] = { OPT_BOOLEAN('x', "exclude-other", &exclude_other, "Only display entries with parent-match"), OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), + OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", + "only consider symbols in these dsos"), OPT_END() }; @@ -1698,6 +1706,14 @@ int cmd_report(int argc, const char **argv, const char *prefix) if (argc) usage_with_options(report_usage, options); + if (dso_list_str) { + dso_list = strlist__new(true, dso_list_str); + if (!dso_list) { + fprintf(stderr, "problems parsing dso list\n"); + exit(129); + } + } + setup_pager(); return __cmd_report(); diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c new file mode 100644 index 0000000000000..025a78edfffe7 --- /dev/null +++ b/tools/perf/util/strlist.c @@ -0,0 +1,184 @@ +/* + * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> + * + * Licensed under the GPLv2. + */ + +#include "strlist.h" +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static struct str_node *str_node__new(const char *s, bool dupstr) +{ + struct str_node *self = malloc(sizeof(*self)); + + if (self != NULL) { + if (dupstr) { + s = strdup(s); + if (s == NULL) + goto out_delete; + } + self->s = s; + } + + return self; + +out_delete: + free(self); + return NULL; +} + +static void str_node__delete(struct str_node *self, bool dupstr) +{ + if (dupstr) + free((void *)self->s); + free(self); +} + +int strlist__add(struct strlist *self, const char *new_entry) +{ + struct rb_node **p = &self->entries.rb_node; + struct rb_node *parent = NULL; + struct str_node *sn; + + while (*p != NULL) { + int rc; + + parent = *p; + sn = rb_entry(parent, struct str_node, rb_node); + rc = strcmp(sn->s, new_entry); + + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return -EEXIST; + } + + sn = str_node__new(new_entry, self->dupstr); + if (sn == NULL) + return -ENOMEM; + + rb_link_node(&sn->rb_node, parent, p); + rb_insert_color(&sn->rb_node, &self->entries); + + return 0; +} + +int strlist__load(struct strlist *self, const char *filename) +{ + char entry[1024]; + int err; + FILE *fp = fopen(filename, "r"); + + if (fp == NULL) + return errno; + + while (fgets(entry, sizeof(entry), fp) != NULL) { + const size_t len = strlen(entry); + + if (len == 0) + continue; + entry[len - 1] = '\0'; + + err = strlist__add(self, entry); + if (err != 0) + goto out; + } + + err = 0; +out: + fclose(fp); + return err; +} + +void strlist__remove(struct strlist *self, struct str_node *sn) +{ + rb_erase(&sn->rb_node, &self->entries); + str_node__delete(sn, self->dupstr); +} + +bool strlist__has_entry(struct strlist *self, const char *entry) +{ + struct rb_node **p = &self->entries.rb_node; + struct rb_node *parent = NULL; + + while (*p != NULL) { + struct str_node *sn; + int rc; + + parent = *p; + sn = rb_entry(parent, struct str_node, rb_node); + rc = strcmp(sn->s, entry); + + if (rc > 0) + p = &(*p)->rb_left; + else if (rc < 0) + p = &(*p)->rb_right; + else + return true; + } + + return false; +} + +static int strlist__parse_list_entry(struct strlist *self, const char *s) +{ + if (strncmp(s, "file://", 7) == 0) + return strlist__load(self, s + 7); + + return strlist__add(self, s); +} + +int strlist__parse_list(struct strlist *self, const char *s) +{ + char *sep; + int err; + + while ((sep = strchr(s, ',')) != NULL) { + *sep = '\0'; + err = strlist__parse_list_entry(self, s); + *sep = ','; + if (err != 0) + return err; + s = sep + 1; + } + + return *s ? strlist__parse_list_entry(self, s) : 0; +} + +struct strlist *strlist__new(bool dupstr, const char *slist) +{ + struct strlist *self = malloc(sizeof(*self)); + + if (self != NULL) { + self->entries = RB_ROOT; + self->dupstr = dupstr; + if (slist && strlist__parse_list(self, slist) != 0) + goto out_error; + } + + return self; +out_error: + free(self); + return NULL; +} + +void strlist__delete(struct strlist *self) +{ + if (self != NULL) { + struct str_node *pos; + struct rb_node *next = rb_first(&self->entries); + + while (next) { + pos = rb_entry(next, struct str_node, rb_node); + next = rb_next(&pos->rb_node); + strlist__remove(self, pos); + } + self->entries = RB_ROOT; + free(self); + } +} diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h new file mode 100644 index 0000000000000..2fb117fb4b676 --- /dev/null +++ b/tools/perf/util/strlist.h @@ -0,0 +1,32 @@ +#ifndef STRLIST_H_ +#define STRLIST_H_ + +#include "rbtree.h" +#include <stdbool.h> + +struct str_node { + struct rb_node rb_node; + const char *s; +}; + +struct strlist { + struct rb_root entries; + bool dupstr; +}; + +struct strlist *strlist__new(bool dupstr, const char *slist); +void strlist__delete(struct strlist *self); + +void strlist__remove(struct strlist *self, struct str_node *sn); +int strlist__load(struct strlist *self, const char *filename); +int strlist__add(struct strlist *self, const char *str); + +bool strlist__has_entry(struct strlist *self, const char *entry); + +static inline bool strlist__empty(const struct strlist *self) +{ + return rb_first(&self->entries) == NULL; +} + +int strlist__parse_list(struct strlist *self, const char *s); +#endif /* STRLIST_H_ */ -- GitLab From cc8b88b15ab8e5ae162a46c4b6b286b555190dd1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Tue, 30 Jun 2009 19:01:21 -0300 Subject: [PATCH 0418/1002] perf report: Add --comms parameter So that we can filter by comm. Symbols in other comms won't be accounted for. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246399282-20934-3-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Documentation/perf-report.txt | 4 +++ tools/perf/builtin-report.c | 33 +++++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 13d85ca8c914e..4c44ef1747b9e 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -24,6 +24,10 @@ OPTIONS --dsos=:: Only consider symbols in these dsos. CSV that understands file://filename entries. +-C:: +--comms=:: + Only consider symbols in these comms. CSV that understands + file://filename entries. SEE ALSO -------- diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7c6b6e776718b..8143477b7ef75 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -33,8 +33,8 @@ static char *vmlinux = NULL; static char default_sort_order[] = "comm,dso"; static char *sort_order = default_sort_order; -static char *dso_list_str; -static struct strlist *dso_list; +static char *dso_list_str, *comm_list_str; +static struct strlist *dso_list, *comm_list; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; @@ -240,7 +240,7 @@ static u64 vdso__map_ip(struct map *map, u64 ip) static inline int is_anon_memory(const char *filename) { - return strcmp(filename, "//anon") == 0; + return strcmp(filename, "//anon") == 0; } static struct map *map__new(struct mmap_event *event) @@ -1253,6 +1253,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) return -1; } + if (comm_list && !strlist__has_entry(comm_list, thread->comm)) + return 0; + if (event->header.misc & PERF_EVENT_MISC_KERNEL) { show = SHOW_KERNEL; level = 'k'; @@ -1667,6 +1670,8 @@ static const struct option options[] = { OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), + OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", + "only consider symbols in these comms"), OPT_END() }; @@ -1685,6 +1690,19 @@ static void setup_sorting(void) free(str); } +static void setup_list(struct strlist **list, const char *list_str, + const char *list_name) +{ + if (list_str) { + *list = strlist__new(true, list_str); + if (!*list) { + fprintf(stderr, "problems parsing %s list\n", + list_name); + exit(129); + } + } +} + int cmd_report(int argc, const char **argv, const char *prefix) { symbol__init(); @@ -1706,13 +1724,8 @@ int cmd_report(int argc, const char **argv, const char *prefix) if (argc) usage_with_options(report_usage, options); - if (dso_list_str) { - dso_list = strlist__new(true, dso_list_str); - if (!dso_list) { - fprintf(stderr, "problems parsing dso list\n"); - exit(129); - } - } + setup_list(&dso_list, dso_list_str, "dso"); + setup_list(&comm_list, comm_list_str, "comm"); setup_pager(); -- GitLab From 7bec7a9134c25cecb0d7029199b59f7b1bef35b8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Tue, 30 Jun 2009 19:01:22 -0300 Subject: [PATCH 0419/1002] perf report: Add --symbols parameter So that we can filter by symbol name. The 'pfunct' utility in the 'dwarves' package can be used to create a file with the functions one wants. Example: [acme@doppio pahole]$ pfunct /usr/lib/debug/usr/lib64/libdw-0.141.so.debug | grep dwarf > /tmp/dwarf.symbols [acme@doppio pahole]$ wc -l /tmp/dwarf.symbols 93 /tmp/dwarf.symbols [acme@doppio pahole]$ head -3 /tmp/dwarf.symbols dwfl_addrdwarf dwfl_module_getdwarf dwfl_getdwarf [acme@doppio pahole]$ perf report --sort comm,dso,symbol --comms pahole --dsos /usr/lib64/libdw-0.141.so --symbols file:///tmp/dwarf.symbols 33.99% pahole /usr/lib64/libdw-0.141.so [.] dwarf_tag 29.07% pahole /usr/lib64/libdw-0.141.so [.] dwarf_decl_file 27.71% pahole /usr/lib64/libdw-0.141.so [.] dwarf_getsrclines 4.54% pahole /usr/lib64/libdw-0.141.so 0x00000000007400 3.93% pahole /usr/lib64/libdw-0.141.so [.] dwarf_decl_line 0.46% pahole /usr/lib64/libdw-0.141.so [.] dwarf_getlocation 0.18% pahole /usr/lib64/libdw-0.141.so [.] __libdwarf_next_prime 0.13% pahole /usr/lib64/libdw-0.141.so [.] dwarf_diecu [acme@doppio pahole]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1246399282-20934-4-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Documentation/perf-report.txt | 4 ++++ tools/perf/builtin-report.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 4c44ef1747b9e..8aa3f8c88707f 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -28,6 +28,10 @@ OPTIONS --comms=:: Only consider symbols in these comms. CSV that understands file://filename entries. +-S:: +--symbols=:: + Only consider these symbols. CSV that understands + file://filename entries. SEE ALSO -------- diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8143477b7ef75..135b7837e6bf3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -33,8 +33,8 @@ static char *vmlinux = NULL; static char default_sort_order[] = "comm,dso"; static char *sort_order = default_sort_order; -static char *dso_list_str, *comm_list_str; -static struct strlist *dso_list, *comm_list; +static char *dso_list_str, *comm_list_str, *sym_list_str; +static struct strlist *dso_list, *comm_list, *sym_list; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; @@ -1281,6 +1281,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name)) return 0; + if (sym_list && sym && !strlist__has_entry(sym_list, sym->name)) + return 0; + if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { eprintf("problem incrementing symbol count, skipping event\n"); return -1; @@ -1672,6 +1675,8 @@ static const struct option options[] = { "only consider symbols in these dsos"), OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", "only consider symbols in these comms"), + OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", + "only consider these symbols"), OPT_END() }; @@ -1726,6 +1731,7 @@ int cmd_report(int argc, const char **argv, const char *prefix) setup_list(&dso_list, dso_list_str, "dso"); setup_list(&comm_list, comm_list_str, "comm"); + setup_list(&sym_list, sym_list_str, "symbol"); setup_pager(); -- GitLab From 789d03f584484af85dbdc64935270c8e45f36ef7 Mon Sep 17 00:00:00 2001 From: Jan Beulich <JBeulich@novell.com> Date: Tue, 30 Jun 2009 11:52:23 +0100 Subject: [PATCH 0420/1002] x86: Fix fixmap ordering The merge of the 32- and 64-bit fixmap headers made a latent bug on x86-64 a real one: with the right config settings it is possible for FIX_OHCI1394_BASE to overlap the FIX_BTMAP_* range. Signed-off-by: Jan Beulich <jbeulich@novell.com> Cc: <stable@kernel.org> # for 2.6.30.x LKML-Reference: <4A4A0A8702000078000082E8@vpn.id2.novell.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/fixmap.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 2d81af3974a07..3eb0f79a53206 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -114,9 +114,6 @@ enum fixed_addresses { FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */ FIX_TEXT_POKE1, __end_of_permanent_fixed_addresses, -#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT - FIX_OHCI1394_BASE, -#endif /* * 256 temporary boot-time mappings, used by early_ioremap(), * before ioremap() is functional. @@ -129,6 +126,9 @@ enum fixed_addresses { FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - (__end_of_permanent_fixed_addresses & 255), FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, +#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT + FIX_OHCI1394_BASE, +#endif #ifdef CONFIG_X86_32 FIX_WP_TEST, #endif -- GitLab From 1f208ea67821703fd4de056ea6f0baa81f4ad4a5 Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:44 +1000 Subject: [PATCH 0421/1002] perf report: Fix -z option Fix a copy and paste error, -z was setting the group option. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230140.714204656@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cf0d21f1ae10e..5c2965562c5d7 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -675,7 +675,7 @@ static const struct option options[] = { "put the counters into a counter group"), OPT_STRING('s', "sym-filter", &sym_filter, "pattern", "only display symbols matchig this pattern"), - OPT_BOOLEAN('z', "zero", &group, + OPT_BOOLEAN('z', "zero", &zero, "zero history across updates"), OPT_INTEGER('F', "freq", &freq, "profile at this frequency"), -- GitLab From 6717534ddc328ae5cdf89f1ef802db83fc451f19 Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:45 +1000 Subject: [PATCH 0422/1002] perf_counter tools: Remove zlib dependency The zlib devel libraries may not be installed and since we aren't using zlib we may as well remove it. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230140.802078956@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 9c6d0ae3708e0..f572c90f610ea 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -381,12 +381,6 @@ ifndef CC_LD_DYNPATH endif endif -ifdef ZLIB_PATH - BASIC_CFLAGS += -I$(ZLIB_PATH)/include - EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib) -endif -EXTLIBS += -lz - ifdef NEEDS_SOCKET EXTLIBS += -lsocket endif -- GitLab From 2ab52083ffc057014e502cf3473adc41436922fa Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:46 +1000 Subject: [PATCH 0423/1002] perf top: Move skip symbols to an array Move the list of symbols we skip into an array, making it easier to add new ones. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230140.904782938@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-top.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5c2965562c5d7..731ec6d79c1c6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -286,11 +286,22 @@ static void *display_thread(void *arg) return NULL; } +/* Tag samples to be skipped. */ +char *skip_symbols[] = { + "default_idle", + "cpu_idle", + "enter_idle", + "exit_idle", + "mwait_idle", + NULL +}; + static int symbol_filter(struct dso *self, struct symbol *sym) { static int filter_match; struct sym_entry *syme; const char *name = sym->name; + int i; if (!strcmp(name, "_text") || !strcmp(name, "_etext") || @@ -302,13 +313,12 @@ static int symbol_filter(struct dso *self, struct symbol *sym) return 1; syme = dso__sym_priv(self, sym); - /* Tag samples to be skipped. */ - if (!strcmp("default_idle", name) || - !strcmp("cpu_idle", name) || - !strcmp("enter_idle", name) || - !strcmp("exit_idle", name) || - !strcmp("mwait_idle", name)) - syme->skip = 1; + for (i = 0; skip_symbols[i]; i++) { + if (!strcmp(skip_symbols[i], name)) { + syme->skip = 1; + break; + } + } if (filter_match == 1) { filter_end = sym->start; -- GitLab From 3a3393ef75a14ae259a82f3f38624efa17884168 Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:47 +1000 Subject: [PATCH 0424/1002] perf top: Add ppc64 specific skip symbols and strip ppc64 . prefix Filter out some ppc64 specific idle loop functions and remove leading '.' on ppc64 text symbols. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230140.995643441@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-top.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 731ec6d79c1c6..0506cd6e04cce 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -293,6 +293,8 @@ char *skip_symbols[] = { "enter_idle", "exit_idle", "mwait_idle", + "ppc64_runlatch_off", + "pseries_dedicated_idle_sleep", NULL }; @@ -303,6 +305,13 @@ static int symbol_filter(struct dso *self, struct symbol *sym) const char *name = sym->name; int i; + /* + * ppc64 uses function descriptors and appends a '.' to the + * start of every instruction address. Remove it. + */ + if (name[0] == '.') + name++; + if (!strcmp(name, "_text") || !strcmp(name, "_etext") || !strcmp(name, "_sinittext") || -- GitLab From d8db1b57d31a6b30ea2f0df318eab50fc92b38d6 Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:48 +1000 Subject: [PATCH 0425/1002] perf report: Fix reporting of hypervisor PERF_EVENT_MISC_* is not a bitmask, so we have to mask and compare. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230141.088394681@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 135b7837e6bf3..88e88c510ae58 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1213,6 +1213,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) struct map *map = NULL; void *more_data = event->ip.__more_data; struct ip_callchain *chain = NULL; + int cpumode; if (sample_type & PERF_SAMPLE_PERIOD) { period = *(u64 *)more_data; @@ -1256,7 +1257,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) if (comm_list && !strlist__has_entry(comm_list, thread->comm)) return 0; - if (event->header.misc & PERF_EVENT_MISC_KERNEL) { + cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK; + + if (cpumode == PERF_EVENT_MISC_KERNEL) { show = SHOW_KERNEL; level = 'k'; @@ -1264,7 +1267,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) dprintf(" ...... dso: %s\n", dso->name); - } else if (event->header.misc & PERF_EVENT_MISC_USER) { + } else if (cpumode == PERF_EVENT_MISC_USER) { show = SHOW_USER; level = '.'; -- GitLab From fb9c818873a788c5c01c9868cc6050df96e2c7df Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 09:00:49 +1000 Subject: [PATCH 0426/1002] perf report: Add hypervisor dso Add a dso for hypervisor samples. We don't get any symbol information on the ppc64 hypervisor but this at least gives us a high level summary of the time spent in there. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org LKML-Reference: <20090630230141.182536873@samba.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 88e88c510ae58..3f5d8ea05ff09 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -121,6 +121,7 @@ typedef union event_union { static LIST_HEAD(dsos); static struct dso *kernel_dso; static struct dso *vdso; +static struct dso *hypervisor_dso; static void dsos__add(struct dso *dso) { @@ -202,6 +203,11 @@ static int load_kernel(void) dsos__add(vdso); + hypervisor_dso = dso__new("[hypervisor]", 0); + if (!hypervisor_dso) + return -1; + dsos__add(hypervisor_dso); + return err; } @@ -640,7 +646,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self) if (self->sym) { ret += fprintf(fp, "[%c] %s", - self->dso == kernel_dso ? 'k' : '.', self->sym->name); + self->dso == kernel_dso ? 'k' : + self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); } else { ret += fprintf(fp, "%#016llx", (u64)self->ip); } @@ -963,6 +970,9 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, } switch (context) { + case PERF_CONTEXT_HV: + dso = hypervisor_dso; + break; case PERF_CONTEXT_KERNEL: dso = kernel_dso; break; @@ -1275,6 +1285,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) } else { show = SHOW_HV; level = 'H'; + + dso = hypervisor_dso; + dprintf(" ...... dso: [hypervisor]\n"); } -- GitLab From 944c54e7fc5ccf961bef2b5449958436b85de459 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Wed, 1 Jul 2009 00:10:16 +0200 Subject: [PATCH 0427/1002] ia64/PCI: adjust section annotation for pcibios_setup() Should be __init. Acked-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- arch/ia64/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 729298f4b2343..7de76dd352fe4 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -537,7 +537,7 @@ pcibios_align_resource (void *data, struct resource *res, /* * PCI BIOS setup, always defaults to SAL interface */ -char * __devinit +char * __init pcibios_setup (char *str) { return str; -- GitLab From 8f6c2e4b325a8e9f8f47febb2fd0ed4fae7d45a9 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" <martin.petersen@oracle.com> Date: Wed, 1 Jul 2009 11:13:45 +1000 Subject: [PATCH 0428/1002] md: Use new topology calls to indicate alignment and I/O sizes Switch MD over to the new disk_stack_limits() function which checks for aligment and adjusts preferred I/O sizes when stacking. Also indicate preferred I/O sizes where applicable. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/linear.c | 4 ++-- drivers/md/multipath.c | 7 ++++--- drivers/md/raid0.c | 9 +++++++-- drivers/md/raid1.c | 9 ++++----- drivers/md/raid10.c | 19 +++++++++++++------ drivers/md/raid5.c | 10 +++++++++- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 15c8b7b25a9b9..5810fa906af08 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -166,8 +166,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) rdev->sectors = sectors * mddev->chunk_sectors; } - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index cbe368fa65987..237fe3fd235c8 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -294,7 +294,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) for (path = first; path <= last; path++) if ((p=conf->multipaths+path)->rdev == NULL) { q = rdev->bdev->bd_disk->queue; - blk_queue_stack_limits(mddev->queue, q); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as @@ -463,9 +464,9 @@ static int multipath_run (mddev_t *mddev) disk = conf->multipaths + disk_idx; disk->rdev = rdev; + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); /* as we don't honour merge_bvec_fn, we must never risk * violating it, not that we ever expect a device with * a merge_bvec_fn to be involved in multipath */ diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index ab4a489d8695f..335f490dcad63 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -170,8 +170,8 @@ static int create_strip_zones(mddev_t *mddev) } dev[j] = rdev1; - blk_queue_stack_limits(mddev->queue, - rdev1->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev1->bdev, + rdev1->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. @@ -250,6 +250,11 @@ static int create_strip_zones(mddev_t *mddev) mddev->chunk_sectors << 9); goto abort; } + + blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); + blk_queue_io_opt(mddev->queue, + (mddev->chunk_sectors << 9) * mddev->raid_disks); + printk(KERN_INFO "raid0: done.\n"); mddev->private = conf; return 0; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 89939a7aef570..0569efba0c02c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1123,8 +1123,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) for (mirror = first; mirror <= last; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. @@ -1988,9 +1988,8 @@ static int run(mddev_t *mddev) disk = conf->mirrors + disk_idx; disk->rdev = rdev; - - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index ae12ceafe10c5..7298a5e5a183f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1151,8 +1151,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) for ( ; mirror <= last ; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. @@ -2044,7 +2044,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) static int run(mddev_t *mddev) { conf_t *conf; - int i, disk_idx; + int i, disk_idx, chunk_size; mirror_info_t *disk; mdk_rdev_t *rdev; int nc, fc, fo; @@ -2130,6 +2130,14 @@ static int run(mddev_t *mddev) spin_lock_init(&conf->device_lock); mddev->queue->queue_lock = &conf->device_lock; + chunk_size = mddev->chunk_sectors << 9; + blk_queue_io_min(mddev->queue, chunk_size); + if (conf->raid_disks % conf->near_copies) + blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks); + else + blk_queue_io_opt(mddev->queue, chunk_size * + (conf->raid_disks / conf->near_copies)); + list_for_each_entry(rdev, &mddev->disks, same_set) { disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks @@ -2138,9 +2146,8 @@ static int run(mddev_t *mddev) disk = conf->mirrors + disk_idx; disk->rdev = rdev; - - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f9f991e6e1389..92ef9b6abfc7a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4452,7 +4452,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) static int run(mddev_t *mddev) { raid5_conf_t *conf; - int working_disks = 0; + int working_disks = 0, chunk_size; mdk_rdev_t *rdev; if (mddev->recovery_cp != MaxSector) @@ -4607,6 +4607,14 @@ static int run(mddev_t *mddev) md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); + chunk_size = mddev->chunk_sectors << 9; + blk_queue_io_min(mddev->queue, chunk_size); + blk_queue_io_opt(mddev->queue, chunk_size * + (conf->raid_disks - conf->max_degraded)); + + list_for_each_entry(rdev, &mddev->disks, same_set) + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); return 0; abort: -- GitLab From b8d966efd9a46a9a35beac50cbff6e30565125ef Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Wed, 1 Jul 2009 11:14:04 +1000 Subject: [PATCH 0429/1002] md: avoid dereferencing NULL pointer when accessing suspend_* sysfs attributes. If we try to modify one of the md/ sysfs files suspend_lo or suspend_hi when the array is not active, we dereference a NULL. Protect against that. Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/md.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 09be637d52cbb..2166af8a76546 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3573,7 +3573,8 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len) char *e; unsigned long long new = simple_strtoull(buf, &e, 10); - if (mddev->pers->quiesce == NULL) + if (mddev->pers == NULL || + mddev->pers->quiesce == NULL) return -EINVAL; if (buf == e || (*e && *e != '\n')) return -EINVAL; @@ -3601,7 +3602,8 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) char *e; unsigned long long new = simple_strtoull(buf, &e, 10); - if (mddev->pers->quiesce == NULL) + if (mddev->pers == NULL || + mddev->pers->quiesce == NULL) return -EINVAL; if (buf == e || (*e && *e != '\n')) return -EINVAL; -- GitLab From 133890103b9de08904f909995973e4b5c08a780e Mon Sep 17 00:00:00 2001 From: Davide Libenzi <davidel@xmailserver.org> Date: Tue, 30 Jun 2009 11:41:11 -0700 Subject: [PATCH 0430/1002] eventfd: revised interface and cleanups Change the eventfd interface to de-couple the eventfd memory context, from the file pointer instance. Without such change, there is no clean way to racely free handle the POLLHUP event sent when the last instance of the file* goes away. Also, now the internal eventfd APIs are using the eventfd context instead of the file*. This patch is required by KVM's IRQfd code, which is still under development. Signed-off-by: Davide Libenzi <davidel@xmailserver.org> Cc: Gregory Haskins <ghaskins@novell.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Benjamin LaHaise <bcrl@kvack.org> Cc: Avi Kivity <avi@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/lguest/lg.h | 2 +- drivers/lguest/lguest_user.c | 4 +- fs/aio.c | 24 ++----- fs/eventfd.c | 122 +++++++++++++++++++++++++++++++---- include/linux/aio.h | 4 +- include/linux/eventfd.h | 35 +++++++--- 6 files changed, 149 insertions(+), 42 deletions(-) diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index d4e8979735cb0..9c3138265f8e4 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h @@ -82,7 +82,7 @@ struct lg_cpu { struct lg_eventfd { unsigned long addr; - struct file *event; + struct eventfd_ctx *event; }; struct lg_eventfd_map { diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 32e297121058a..9f9a2953b3830 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -50,7 +50,7 @@ static int add_eventfd(struct lguest *lg, unsigned long addr, int fd) /* Now append new entry. */ new->map[new->num].addr = addr; - new->map[new->num].event = eventfd_fget(fd); + new->map[new->num].event = eventfd_ctx_fdget(fd); if (IS_ERR(new->map[new->num].event)) { kfree(new); return PTR_ERR(new->map[new->num].event); @@ -357,7 +357,7 @@ static int close(struct inode *inode, struct file *file) /* Release any eventfds they registered. */ for (i = 0; i < lg->eventfds->num; i++) - fput(lg->eventfds->map[i].event); + eventfd_ctx_put(lg->eventfds->map[i].event); kfree(lg->eventfds); /* If lg->dead doesn't contain an error code it will be NULL or a diff --git a/fs/aio.c b/fs/aio.c index 76da12537956c..d065b2c3273ea 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -485,6 +485,8 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) { assert_spin_locked(&ctx->ctx_lock); + if (req->ki_eventfd != NULL) + eventfd_ctx_put(req->ki_eventfd); if (req->ki_dtor) req->ki_dtor(req); if (req->ki_iovec != &req->ki_inline_vec) @@ -509,8 +511,6 @@ static void aio_fput_routine(struct work_struct *data) /* Complete the fput(s) */ if (req->ki_filp != NULL) __fput(req->ki_filp); - if (req->ki_eventfd != NULL) - __fput(req->ki_eventfd); /* Link the iocb into the context's free list */ spin_lock_irq(&ctx->ctx_lock); @@ -528,8 +528,6 @@ static void aio_fput_routine(struct work_struct *data) */ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) { - int schedule_putreq = 0; - dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n", req, atomic_long_read(&req->ki_filp->f_count)); @@ -549,24 +547,16 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) * we would not be holding the last reference to the file*, so * this function will be executed w/out any aio kthread wakeup. */ - if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) - schedule_putreq++; - else - req->ki_filp = NULL; - if (req->ki_eventfd != NULL) { - if (unlikely(atomic_long_dec_and_test(&req->ki_eventfd->f_count))) - schedule_putreq++; - else - req->ki_eventfd = NULL; - } - if (unlikely(schedule_putreq)) { + if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) { get_ioctx(ctx); spin_lock(&fput_lock); list_add(&req->ki_list, &fput_head); spin_unlock(&fput_lock); queue_work(aio_wq, &fput_work); - } else + } else { + req->ki_filp = NULL; really_put_req(ctx, req); + } return 1; } @@ -1622,7 +1612,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, * an eventfd() fd, and will be signaled for each completed * event using the eventfd_signal() function. */ - req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd); + req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd); if (IS_ERR(req->ki_eventfd)) { ret = PTR_ERR(req->ki_eventfd); req->ki_eventfd = NULL; diff --git a/fs/eventfd.c b/fs/eventfd.c index 3f0e1974abdcf..31d12de83a2a9 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -14,35 +14,44 @@ #include <linux/list.h> #include <linux/spinlock.h> #include <linux/anon_inodes.h> -#include <linux/eventfd.h> #include <linux/syscalls.h> #include <linux/module.h> +#include <linux/kref.h> +#include <linux/eventfd.h> struct eventfd_ctx { + struct kref kref; wait_queue_head_t wqh; /* * Every time that a write(2) is performed on an eventfd, the * value of the __u64 being written is added to "count" and a * wakeup is performed on "wqh". A read(2) will return the "count" * value to userspace, and will reset "count" to zero. The kernel - * size eventfd_signal() also, adds to the "count" counter and + * side eventfd_signal() also, adds to the "count" counter and * issue a wakeup. */ __u64 count; unsigned int flags; }; -/* - * Adds "n" to the eventfd counter "count". Returns "n" in case of - * success, or a value lower then "n" in case of coutner overflow. - * This function is supposed to be called by the kernel in paths - * that do not allow sleeping. In this function we allow the counter - * to reach the ULLONG_MAX value, and we signal this as overflow - * condition by returining a POLLERR to poll(2). +/** + * eventfd_signal - Adds @n to the eventfd counter. + * @ctx: [in] Pointer to the eventfd context. + * @n: [in] Value of the counter to be added to the eventfd internal counter. + * The value cannot be negative. + * + * This function is supposed to be called by the kernel in paths that do not + * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX + * value, and we signal this as overflow condition by returining a POLLERR + * to poll(2). + * + * Returns @n in case of success, a non-negative number lower than @n in case + * of overflow, or the following error codes: + * + * -EINVAL : The value of @n is negative. */ -int eventfd_signal(struct file *file, int n) +int eventfd_signal(struct eventfd_ctx *ctx, int n) { - struct eventfd_ctx *ctx = file->private_data; unsigned long flags; if (n < 0) @@ -59,9 +68,45 @@ int eventfd_signal(struct file *file, int n) } EXPORT_SYMBOL_GPL(eventfd_signal); +static void eventfd_free(struct kref *kref) +{ + struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref); + + kfree(ctx); +} + +/** + * eventfd_ctx_get - Acquires a reference to the internal eventfd context. + * @ctx: [in] Pointer to the eventfd context. + * + * Returns: In case of success, returns a pointer to the eventfd context. + */ +struct eventfd_ctx *eventfd_ctx_get(struct eventfd_ctx *ctx) +{ + kref_get(&ctx->kref); + return ctx; +} +EXPORT_SYMBOL_GPL(eventfd_ctx_get); + +/** + * eventfd_ctx_put - Releases a reference to the internal eventfd context. + * @ctx: [in] Pointer to eventfd context. + * + * The eventfd context reference must have been previously acquired either + * with eventfd_ctx_get() or eventfd_ctx_fdget()). + */ +void eventfd_ctx_put(struct eventfd_ctx *ctx) +{ + kref_put(&ctx->kref, eventfd_free); +} +EXPORT_SYMBOL_GPL(eventfd_ctx_put); + static int eventfd_release(struct inode *inode, struct file *file) { - kfree(file->private_data); + struct eventfd_ctx *ctx = file->private_data; + + wake_up_poll(&ctx->wqh, POLLHUP); + eventfd_ctx_put(ctx); return 0; } @@ -185,6 +230,16 @@ static const struct file_operations eventfd_fops = { .write = eventfd_write, }; +/** + * eventfd_fget - Acquire a reference of an eventfd file descriptor. + * @fd: [in] Eventfd file descriptor. + * + * Returns a pointer to the eventfd file structure in case of success, or the + * following error pointer: + * + * -EBADF : Invalid @fd file descriptor. + * -EINVAL : The @fd file descriptor is not an eventfd file. + */ struct file *eventfd_fget(int fd) { struct file *file; @@ -201,6 +256,48 @@ struct file *eventfd_fget(int fd) } EXPORT_SYMBOL_GPL(eventfd_fget); +/** + * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context. + * @fd: [in] Eventfd file descriptor. + * + * Returns a pointer to the internal eventfd context, otherwise the error + * pointers returned by the following functions: + * + * eventfd_fget + */ +struct eventfd_ctx *eventfd_ctx_fdget(int fd) +{ + struct file *file; + struct eventfd_ctx *ctx; + + file = eventfd_fget(fd); + if (IS_ERR(file)) + return (struct eventfd_ctx *) file; + ctx = eventfd_ctx_get(file->private_data); + fput(file); + + return ctx; +} +EXPORT_SYMBOL_GPL(eventfd_ctx_fdget); + +/** + * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context. + * @file: [in] Eventfd file pointer. + * + * Returns a pointer to the internal eventfd context, otherwise the error + * pointer: + * + * -EINVAL : The @fd file descriptor is not an eventfd file. + */ +struct eventfd_ctx *eventfd_ctx_fileget(struct file *file) +{ + if (file->f_op != &eventfd_fops) + return ERR_PTR(-EINVAL); + + return eventfd_ctx_get(file->private_data); +} +EXPORT_SYMBOL_GPL(eventfd_ctx_fileget); + SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) { int fd; @@ -217,6 +314,7 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) if (!ctx) return -ENOMEM; + kref_init(&ctx->kref); init_waitqueue_head(&ctx->wqh); ctx->count = count; ctx->flags = flags; diff --git a/include/linux/aio.h b/include/linux/aio.h index b16a957030f87..47f7d932a01d5 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -121,9 +121,9 @@ struct kiocb { /* * If the aio_resfd field of the userspace iocb is not zero, - * this is the underlying file* to deliver event to. + * this is the underlying eventfd context to deliver events to. */ - struct file *ki_eventfd; + struct eventfd_ctx *ki_eventfd; }; #define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY) diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h index f45a8ae5f8281..3b85ba6479f48 100644 --- a/include/linux/eventfd.h +++ b/include/linux/eventfd.h @@ -8,10 +8,8 @@ #ifndef _LINUX_EVENTFD_H #define _LINUX_EVENTFD_H -#ifdef CONFIG_EVENTFD - -/* For O_CLOEXEC and O_NONBLOCK */ #include <linux/fcntl.h> +#include <linux/file.h> /* * CAREFUL: Check include/asm-generic/fcntl.h when defining @@ -27,16 +25,37 @@ #define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK) #define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE) +#ifdef CONFIG_EVENTFD + +struct eventfd_ctx *eventfd_ctx_get(struct eventfd_ctx *ctx); +void eventfd_ctx_put(struct eventfd_ctx *ctx); struct file *eventfd_fget(int fd); -int eventfd_signal(struct file *file, int n); +struct eventfd_ctx *eventfd_ctx_fdget(int fd); +struct eventfd_ctx *eventfd_ctx_fileget(struct file *file); +int eventfd_signal(struct eventfd_ctx *ctx, int n); #else /* CONFIG_EVENTFD */ -#define eventfd_fget(fd) ERR_PTR(-ENOSYS) -static inline int eventfd_signal(struct file *file, int n) -{ return 0; } +/* + * Ugly ugly ugly error layer to support modules that uses eventfd but + * pretend to work in !CONFIG_EVENTFD configurations. Namely, AIO. + */ +static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd) +{ + return ERR_PTR(-ENOSYS); +} + +static inline int eventfd_signal(struct eventfd_ctx *ctx, int n) +{ + return -ENOSYS; +} + +static inline void eventfd_ctx_put(struct eventfd_ctx *ctx) +{ + +} -#endif /* CONFIG_EVENTFD */ +#endif #endif /* _LINUX_EVENTFD_H */ -- GitLab From 2a2325e6e8a3782795fb520220c36fd805775972 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 30 Jun 2009 11:41:13 -0700 Subject: [PATCH 0431/1002] gcov: fix __ctors_start alignment The ctors section for each object file is eight byte aligned (on 64 bit). However the __ctors_start symbol starts at an arbitrary address dependent on the size of the previous sections. Therefore the linker may add some zeroes after __ctors_start to make sure the ctors contents are properly aligned. However the extra zeroes at the beginning aren't expected by the code. When walking the functions pointers contained in there and extra zeroes are added this may result in random jumps. So make sure that the __ctors_start symbol is always aligned as well. Fixes this crash on an allyesconfig on s390: [ 0.582482] Kernel BUG at 0000000000000012 [verbose debug info unavailable] [ 0.582489] illegal operation: 0001 [#1] SMP DEBUG_PAGEALLOC [ 0.582496] Modules linked in: [ 0.582501] CPU: 0 Tainted: G W 2.6.31-rc1-dirty #273 [ 0.582506] Process swapper (pid: 1, task: 000000003f218000, ksp: 000000003f2238e8) [ 0.582510] Krnl PSW : 0704200180000000 0000000000000012 (0x12) [ 0.582518] R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 [ 0.582524] Krnl GPRS: 0000000000036727 0000000000000010 0000000000000001 0000000000000001 [ 0.582529] 00000000001dfefa 0000000000000000 0000000000000000 0000000000000040 [ 0.582534] 0000000001fff0f0 0000000001790628 0000000002296048 0000000002296048 [ 0.582540] 00000000020c438e 0000000001786000 0000000002014a66 000000003f223e60 [ 0.582553] Krnl Code:>0000000000000012: 0000 unknown [ 0.582559] 0000000000000014: 0000 unknown [ 0.582564] 0000000000000016: 0000 unknown [ 0.582570] 0000000000000018: 0000 unknown [ 0.582575] 000000000000001a: 0000 unknown [ 0.582580] 000000000000001c: 0000 unknown [ 0.582585] 000000000000001e: 0000 unknown [ 0.582591] 0000000000000020: 0000 unknown [ 0.582596] Call Trace: [ 0.582599] ([<0000000002014a46>] kernel_init+0x622/0x7a0) [ 0.582607] [<0000000000113e22>] kernel_thread_starter+0x6/0xc [ 0.582615] [<0000000000113e1c>] kernel_thread_starter+0x0/0xc [ 0.582621] INFO: lockdep is turned off. [ 0.582624] Last Breaking-Event-Address: [ 0.582627] [<0000000002014a64>] kernel_init+0x640/0x7a0 Cc: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/asm-generic/vmlinux.lds.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 92b73b6140ff4..dccdbed05848f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -441,7 +441,8 @@ } #ifdef CONFIG_CONSTRUCTORS -#define KERNEL_CTORS() VMLINUX_SYMBOL(__ctors_start) = .; \ +#define KERNEL_CTORS() . = ALIGN(8); \ + VMLINUX_SYMBOL(__ctors_start) = .; \ *(.ctors) \ VMLINUX_SYMBOL(__ctors_end) = .; #else -- GitLab From c15e504bd008aedfcd2219051055b66bffdb6148 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Tue, 30 Jun 2009 11:41:13 -0700 Subject: [PATCH 0432/1002] MAINTAINERS: update EDAC-I82975X As per Ranganathan's request. Signed-off-by: Joe Perches <joe@perches.com> Cc: Ranganathan Desikan <ravi@jetztechnologies.com> Cc: Arvind R. <arvind@jetztechnologies.com> Cc: Doug Thompson <norsk5@yahoo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 05a9a563042f0..92fe0796cd1b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2130,9 +2130,9 @@ F: drivers/edac/i5400_edac.c EDAC-I82975X P: Ranganathan Desikan -M: rdesikan@jetzbroadband.com +M: ravi@jetztechnologies.com P: Arvind R. -M: arvind@acarlab.com +M: arvind@jetztechnologies.com L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained -- GitLab From 15e3252464432a29c5461325cb5243471bd2a219 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell <sfr@canb.auug.org.au> Date: Tue, 30 Jun 2009 11:41:15 -0700 Subject: [PATCH 0433/1002] fbdev: work around old compiler bug When building with a 4.1.x compiler on powerpc64 (at least) we get this error: drivers/video/logo/logo_linux_mono.c:81: error: logo_linux_mono causes a section type conflict This was introduced by commit ae52bb2384f721562f15f719de1acb8e934733cb ("fbdev: move logo externs to header file"). This is a partial revert of that commit sufficient to not hit the compiler bug. Also convert _clut arrays from __initconst to __initdata. Sam said: Al analysed this some time ago. When we say something is const then _sometimes_ gcc annotate the section as const(?) - sometimes not. So if we have two variables/functions annotated __*const and gcc decides to annotate the section const only in one case we get a section type conflict. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Cc: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Cc: Kyle McMartin <kyle@mcmartin.ca> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/pnmtologo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pnmtologo.c b/scripts/pnmtologo.c index 64f5ddb09ea62..5c113123ed9f2 100644 --- a/scripts/pnmtologo.c +++ b/scripts/pnmtologo.c @@ -237,7 +237,7 @@ static void write_header(void) fprintf(out, " * Linux logo %s\n", logoname); fputs(" */\n\n", out); fputs("#include <linux/linux_logo.h>\n\n", out); - fprintf(out, "static const unsigned char %s_data[] __initconst = {\n", + fprintf(out, "static unsigned char %s_data[] __initdata = {\n", logoname); } @@ -374,7 +374,7 @@ static void write_logo_clut224(void) fputs("\n};\n\n", out); /* write logo clut */ - fprintf(out, "static const unsigned char %s_clut[] __initconst = {\n", + fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", logoname); write_hex_cnt = 0; for (i = 0; i < logo_clutsize; i++) { -- GitLab From b01e8dc34379f4ba2f454390e340a025edbaaa7e Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Tue, 30 Jun 2009 11:41:18 -0700 Subject: [PATCH 0434/1002] alpha: fix percpu build breakage alpha percpu access requires custom SHIFT_PERCPU_PTR() definition for modules to work around addressing range limitation. This is done via generating inline assembly using C preprocessing which forces the assembler to generate external reference. This happens behind the compiler's back and makes the compiler think that static percpu variables in modules are unused. This used to be worked around by using __unused attribute for percpu variables which prevent the compiler from omitting the variable; however, recent declare/definition attribute unification change broke this as __used can't be used for declaration. Also, in the process, PER_CPU_ATTRIBUTES definition in alpha percpu.h got broken. This patch adds PER_CPU_DEF_ATTRIBUTES which is only used for definitions and make alpha use it to add __used for percpu variables in modules. This also fixes the PER_CPU_ATTRIBUTES double definition bug. Signed-off-by: Tejun Heo <tj@kernel.org> Tested-by: maximilian attems <max@stro.at> Acked-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Richard Henderson <rth@twiddle.net> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/alpha/include/asm/percpu.h | 6 +++--- include/asm-generic/percpu.h | 4 ++++ include/linux/percpu-defs.h | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/alpha/include/asm/percpu.h b/arch/alpha/include/asm/percpu.h index 06c5c7a4afd3f..b663f1f10b6a1 100644 --- a/arch/alpha/include/asm/percpu.h +++ b/arch/alpha/include/asm/percpu.h @@ -30,7 +30,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #ifndef MODULE #define SHIFT_PERCPU_PTR(var, offset) RELOC_HIDE(&per_cpu_var(var), (offset)) -#define PER_CPU_ATTRIBUTES +#define PER_CPU_DEF_ATTRIBUTES #else /* * To calculate addresses of locally defined variables, GCC uses 32-bit @@ -49,7 +49,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; : "=&r"(__ptr), "=&r"(tmp_gp)); \ (typeof(&per_cpu_var(var)))(__ptr + (offset)); }) -#define PER_CPU_ATTRIBUTES __used +#define PER_CPU_DEF_ATTRIBUTES __used #endif /* MODULE */ @@ -71,7 +71,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #define __get_cpu_var(var) per_cpu_var(var) #define __raw_get_cpu_var(var) per_cpu_var(var) -#define PER_CPU_ATTRIBUTES +#define PER_CPU_DEF_ATTRIBUTES #endif /* SMP */ diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index d7d50d7ee51ec..aa00800adaccd 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -97,4 +97,8 @@ extern void setup_per_cpu_areas(void); #define PER_CPU_ATTRIBUTES #endif +#ifndef PER_CPU_DEF_ATTRIBUTES +#define PER_CPU_DEF_ATTRIBUTES +#endif + #endif /* _ASM_GENERIC_PERCPU_H_ */ diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h index 8f921d74f49f1..68438e18fff4f 100644 --- a/include/linux/percpu-defs.h +++ b/include/linux/percpu-defs.h @@ -24,7 +24,8 @@ #define DEFINE_PER_CPU_SECTION(type, name, section) \ __attribute__((__section__(PER_CPU_BASE_SECTION section))) \ - PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name + PER_CPU_ATTRIBUTES PER_CPU_DEF_ATTRIBUTES \ + __typeof__(type) per_cpu__##name /* * Variant on the per-CPU variable declaration/definition theme used for -- GitLab From 972c71a3183ab41c0b1a9e50842be7e3e980954f Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Date: Tue, 30 Jun 2009 11:41:20 -0700 Subject: [PATCH 0435/1002] gcov: fix documentation Commonly available versions of cp and tar don't work well with special files created using seq_file. Mention this problem in the gcov documentation and update the helper script example to work around these problems. Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/gcov.txt | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Documentation/gcov.txt b/Documentation/gcov.txt index e716aadb3a337..40ec633527600 100644 --- a/Documentation/gcov.txt +++ b/Documentation/gcov.txt @@ -188,13 +188,18 @@ Solution: Exclude affected source files from profiling by specifying GCOV_PROFILE := n or GCOV_PROFILE_basename.o := n in the corresponding Makefile. +Problem: Files copied from sysfs appear empty or incomplete. +Cause: Due to the way seq_file works, some tools such as cp or tar + may not correctly copy files from sysfs. +Solution: Use 'cat' to read .gcda files and 'cp -d' to copy links. + Alternatively use the mechanism shown in Appendix B. + Appendix A: gather_on_build.sh ============================== Sample script to gather coverage meta files on the build machine (see 6a): - #!/bin/bash KSRC=$1 @@ -226,7 +231,7 @@ Appendix B: gather_on_test.sh Sample script to gather coverage data files on the test machine (see 6b): -#!/bin/bash +#!/bin/bash -e DEST=$1 GCDA=/sys/kernel/debug/gcov @@ -236,11 +241,13 @@ if [ -z "$DEST" ] ; then exit 1 fi -find $GCDA -name '*.gcno' -o -name '*.gcda' | tar cfz $DEST -T - +TEMPDIR=$(mktemp -d) +echo Collecting data.. +find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \; +find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \; +find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \; +tar czf $DEST -C $TEMPDIR sys +rm -rf $TEMPDIR -if [ $? -eq 0 ] ; then - echo "$DEST successfully created, copy to build system and unpack with:" - echo " tar xfz $DEST" -else - echo "Could not create file $DEST" -fi +echo "$DEST successfully created, copy to build system and unpack with:" +echo " tar xfz $DEST" -- GitLab From c4285b47b0514e2103584ee829246f813e7ae323 Mon Sep 17 00:00:00 2001 From: Michael Buesch <mb@bu3sch.de> Date: Tue, 30 Jun 2009 11:41:21 -0700 Subject: [PATCH 0436/1002] parport/serial: add support for NetMos 9901 Multi-IO card Add support for the PCI-Express NetMos 9901 Multi-IO card. 0001:06:00.0 Serial controller [0700]: NetMos Technology Device [9710:9901] (prog-if 02 [16550]) Subsystem: Device [a000:1000] Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0, Cache Line Size: 64 bytes Interrupt: pin A routed to IRQ 65 Region 0: I/O ports at 0030 [size=8] Region 1: Memory at 80105000 (32-bit, non-prefetchable) [size=4K] Region 4: Memory at 80104000 (32-bit, non-prefetchable) [size=4K] Capabilities: <access denied> Kernel driver in use: serial Kernel modules: 8250_pci 0001:06:00.1 Serial controller [0700]: NetMos Technology Device [9710:9901] (prog-if 02 [16550]) Subsystem: Device [a000:1000] Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0, Cache Line Size: 64 bytes Interrupt: pin B routed to IRQ 65 Region 0: I/O ports at 0020 [size=8] Region 1: Memory at 80103000 (32-bit, non-prefetchable) [size=4K] Region 4: Memory at 80102000 (32-bit, non-prefetchable) [size=4K] Capabilities: <access denied> Kernel driver in use: serial Kernel modules: 8250_pci 0001:06:00.2 Parallel controller [0701]: NetMos Technology Device [9710:9901] (prog-if 03 [IEEE1284]) Subsystem: Device [a000:2000] Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0, Cache Line Size: 64 bytes Interrupt: pin C routed to IRQ 65 Region 0: I/O ports at 0010 [size=8] Region 1: I/O ports at <unassigned> Region 2: Memory at 80101000 (32-bit, non-prefetchable) [size=4K] Region 4: Memory at 80100000 (32-bit, non-prefetchable) [size=4K] Capabilities: <access denied> Kernel driver in use: parport_pc Kernel modules: parport_pc [ 16.760181] PCI parallel port detected: 416c:0100, I/O at 0x812010(0x0), IRQ 65 [ 16.760225] parport0: PC-style at 0x812010, irq 65 [PCSPP,TRISTATE,EPP] [ 16.851842] serial 0001:06:00.0: enabling device (0004 -> 0007) [ 16.883776] 0001:06:00.0: ttyS0 at I/O 0x812030 (irq = 65) is a ST16650V2 [ 16.893832] serial 0001:06:00.1: enabling device (0004 -> 0007) [ 16.926537] 0001:06:00.1: ttyS1 at I/O 0x812020 (irq = 65) is a ST16650V2 Signed-off-by: Michael Buesch <mb@bu3sch.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/parport/parport_pc.c | 5 ++++- drivers/serial/8250_pci.c | 6 ++++++ include/linux/pci_ids.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 1032d5fdbd423..2597145a066e3 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2907,6 +2907,7 @@ enum parport_pc_pci_cards { netmos_9755, netmos_9805, netmos_9815, + netmos_9901, quatech_sppxp100, }; @@ -2987,7 +2988,7 @@ static struct parport_pc_pci { /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, - + /* netmos_9901 */ { 1, { { 0, -1 }, } }, /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, }; @@ -3089,6 +3090,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, + 0xA000, 0x2000, 0, 0, netmos_9901 }, /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index a07015d646dda..6160e03f410ce 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -759,6 +759,8 @@ static int pci_netmos_init(struct pci_dev *dev) /* subdevice 0x00PS means <P> parallel, <S> serial */ unsigned int num_serial = dev->subsystem_device & 0xf; + if (dev->device == PCI_DEVICE_ID_NETMOS_9901) + return 0; if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && dev->subsystem_device == 0x0299) return 0; @@ -3557,6 +3559,10 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_VENDOR_ID_IBM, 0x0299, 0, 0, pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a3b0003657955..73b46b6b904fc 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2645,6 +2645,7 @@ #define PCI_DEVICE_ID_NETMOS_9835 0x9835 #define PCI_DEVICE_ID_NETMOS_9845 0x9845 #define PCI_DEVICE_ID_NETMOS_9855 0x9855 +#define PCI_DEVICE_ID_NETMOS_9901 0x9901 #define PCI_VENDOR_ID_3COM_2 0xa727 -- GitLab From b1cfebc9231a69d46d66982a2c856ba41ef6d6b9 Mon Sep 17 00:00:00 2001 From: Yang Shi <yang.shi@windriver.com> Date: Tue, 30 Jun 2009 11:41:22 -0700 Subject: [PATCH 0437/1002] edac: add DDR3 memory type for MPC85xx EDAC Since some new MPC85xx SOCs support DDR3 memory now, so add DDR3 memory type for MPC85xx EDAC. Signed-off-by: Yang Shi <yang.shi@windriver.com> Cc: Doug Thompson <norsk5@yahoo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/edac/edac_core.h | 4 ++++ drivers/edac/edac_mc_sysfs.c | 4 +++- drivers/edac/mpc85xx_edac.c | 6 ++++++ drivers/edac/mpc85xx_edac.h | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 3493c6bdb8206..871c13b4c1489 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -150,6 +150,8 @@ enum mem_type { MEM_FB_DDR2, /* fully buffered DDR2 */ MEM_RDDR2, /* Registered DDR2 RAM */ MEM_XDR, /* Rambus XDR */ + MEM_DDR3, /* DDR3 RAM */ + MEM_RDDR3, /* Registered DDR3 RAM */ }; #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) @@ -167,6 +169,8 @@ enum mem_type { #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) #define MEM_FLAG_XDR BIT(MEM_XDR) +#define MEM_FLAG_DDR3 BIT(MEM_DDR3) +#define MEM_FLAG_RDDR3 BIT(MEM_RDDR3) /* chipset Error Detection and Correction capabilities and mode */ enum edac_type { diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index ad218fe4942df..e1d4ce0834813 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -94,7 +94,9 @@ static const char *mem_types[] = { [MEM_DDR2] = "Unbuffered-DDR2", [MEM_FB_DDR2] = "FullyBuffered-DDR2", [MEM_RDDR2] = "Registered-DDR2", - [MEM_XDR] = "XDR" + [MEM_XDR] = "XDR", + [MEM_DDR3] = "Unbuffered-DDR3", + [MEM_RDDR3] = "Registered-DDR3" }; static const char *dev_types[] = { diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 7c8c2d72916f6..3f2ccfc6407c2 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -757,6 +757,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) case DSC_SDTYPE_DDR2: mtype = MEM_RDDR2; break; + case DSC_SDTYPE_DDR3: + mtype = MEM_RDDR3; + break; default: mtype = MEM_UNKNOWN; break; @@ -769,6 +772,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) case DSC_SDTYPE_DDR2: mtype = MEM_DDR2; break; + case DSC_SDTYPE_DDR3: + mtype = MEM_DDR3; + break; default: mtype = MEM_UNKNOWN; break; diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index 135b3539a030d..52432ee7c4b98 100644 --- a/drivers/edac/mpc85xx_edac.h +++ b/drivers/edac/mpc85xx_edac.h @@ -53,6 +53,7 @@ #define DSC_SDTYPE_DDR 0x02000000 #define DSC_SDTYPE_DDR2 0x03000000 +#define DSC_SDTYPE_DDR3 0x07000000 #define DSC_X32_EN 0x00000020 /* Err_Int_En */ -- GitLab From 341c87bf346f57748230628c5ad6ee69219250e8 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Date: Tue, 30 Jun 2009 11:41:23 -0700 Subject: [PATCH 0438/1002] elf: limit max map count to safe value With ELF, at generating coredump, some more headers other than used vmas are added. When max_map_count == 65536, a core generated by following kinds of code can be unreadable because the number of ELF's program header is written in 16bit in Ehdr (please see elf.h) and the number overflows. == ... = mmap(); (munmap, mprotect, etc...) if (failed) abort(); == This can happen in mmap/munmap/mprotect/etc...which calls split_vma(). I think 65536 is not safe as _default_ and reduce it to 65530 is good for avoiding unexpected corrupted core. Anyway, max_map_count can be enlarged by sysctl if a user is brave.. Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk> Cc: Jakub Jelinek <jakub@redhat.com> Acked-by: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/binfmt_elf.c | 5 ++++- include/linux/sched.h | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 9fa212b014a50..f1867900e4594 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1929,7 +1929,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un elf = kmalloc(sizeof(*elf), GFP_KERNEL); if (!elf) goto out; - + /* + * The number of segs are recored into ELF header as 16bit value. + * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. + */ segs = current->mm->map_count; #ifdef ELF_CORE_EXTRA_PHDRS segs += ELF_CORE_EXTRA_PHDRS; diff --git a/include/linux/sched.h b/include/linux/sched.h index 4d07542698842..0085d758d6453 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -349,8 +349,20 @@ extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner); struct nsproxy; struct user_namespace; -/* Maximum number of active map areas.. This is a random (large) number */ -#define DEFAULT_MAX_MAP_COUNT 65536 +/* + * Default maximum number of active map areas, this limits the number of vmas + * per mm struct. Users can overwrite this number by sysctl but there is a + * problem. + * + * When a program's coredump is generated as ELF format, a section is created + * per a vma. In ELF, the number of sections is represented in unsigned short. + * This means the number of sections should be smaller than 65535 at coredump. + * Because the kernel adds some informative sections to a image of program at + * generating coredump, we need some margin. The number of extra sections is + * 1-3 now and depends on arch. We use "5" as safe margin, here. + */ +#define MAPCOUNT_ELF_CORE_MARGIN (5) +#define DEFAULT_MAX_MAP_COUNT (USHORT_MAX - MAPCOUNT_ELF_CORE_MARGIN) extern int sysctl_max_map_count; -- GitLab From 4d6c13f87db12ae1ce35ea6a15688ac72419b133 Mon Sep 17 00:00:00 2001 From: Bryan Donlan <bdonlan@gmail.com> Date: Tue, 30 Jun 2009 11:41:24 -0700 Subject: [PATCH 0439/1002] ext2: return -EIO not -ESTALE on directory traversal through deleted inode ext2_iget() returns -ESTALE if invoked on a deleted inode, in order to report errors to NFS properly. However, in ext[234]_lookup(), this -ESTALE can be propagated to userspace if the filesystem is corrupted such that a directory entry references a deleted inode. This leads to a misleading error message - "Stale NFS file handle" - and confusion on the part of the admin. The bug can be easily reproduced by creating a new filesystem, making a link to an unused inode using debugfs, then mounting and attempting to ls -l said link. This patch thus changes ext2_lookup to return -EIO if it receives -ESTALE from ext2_iget(), as ext2 does for other filesystem metadata corruption; and also invokes the appropriate ext*_error functions when this case is detected. Signed-off-by: Bryan Donlan <bdonlan@gmail.com> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/ext2/namei.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 6524ecaebb7a6..e1dedb0f78731 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -66,8 +66,16 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str inode = NULL; if (ino) { inode = ext2_iget(dir->i_sb, ino); - if (IS_ERR(inode)) - return ERR_CAST(inode); + if (unlikely(IS_ERR(inode))) { + if (PTR_ERR(inode) == -ESTALE) { + ext2_error(dir->i_sb, __func__, + "deleted inode referenced: %lu", + ino); + return ERR_PTR(-EIO); + } else { + return ERR_CAST(inode); + } + } } return d_splice_alias(inode, dentry); } -- GitLab From c49568235dd7b4a2ffad63aa950562f4ffb9455f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner <tglx@linutronix.de> Date: Tue, 30 Jun 2009 11:41:25 -0700 Subject: [PATCH 0440/1002] dmapools: protect page_list walk in show_pools() show_pools() walks the page_list of a pool w/o protection against the list modifications in alloc/free. Take pool->lock to avoid stomping into nirvana. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/dmapool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/dmapool.c b/mm/dmapool.c index b1f0885dda227..3df063706f53e 100644 --- a/mm/dmapool.c +++ b/mm/dmapool.c @@ -86,10 +86,12 @@ show_pools(struct device *dev, struct device_attribute *attr, char *buf) unsigned pages = 0; unsigned blocks = 0; + spin_lock_irq(&pool->lock); list_for_each_entry(page, &pool->page_list, page_list) { pages++; blocks += page->in_use; } + spin_unlock_irq(&pool->lock); /* per-pool info, no real statistics yet */ temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n", -- GitLab From b55f627feeb9d48fdbde3835e18afbc76712e49b Mon Sep 17 00:00:00 2001 From: David Brownell <dbrownell@users.sourceforge.net> Date: Tue, 30 Jun 2009 11:41:26 -0700 Subject: [PATCH 0441/1002] spi: new spi->mode bits Add two new spi_device.mode bits to accomodate more protocol options, and pass them through to usermode drivers: * SPI_NO_CS ... a second 3-wire variant, where the chipselect line is removed instead of a data line; transfers are still full duplex. This obviously has STRONG protocol implications since the chipselect transitions can't be used to synchronize state transitions with the SPI master. * SPI_READY ... defines open drain signal that's pulled low to pause the clock. This defines a 5-wire variant (normal 4-wire SPI plus READY) and two 4-wire variants (READY plus each of the 3-wire flavors). Such hardware flow control can be a big win. There are ADC converters and flash chips that expose READY signals, but not many host controllers support it today. The spi_bitbang code should be changed to use SPI_NO_CS instead of its current nonportable hack. That's a mode most hardware can easily support (unlike SPI_READY). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: "Paulraj, Sandeep" <s-paulraj@ti.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/spi/spidev_test.c | 10 +++++++++- drivers/spi/spidev.c | 17 +++++++++++------ include/linux/spi/spi.h | 2 ++ include/linux/spi/spidev.h | 2 ++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c index cf0e3ce0d5268..c1a5aad3c75a9 100644 --- a/Documentation/spi/spidev_test.c +++ b/Documentation/spi/spidev_test.c @@ -99,11 +99,13 @@ void parse_opts(int argc, char *argv[]) { "lsb", 0, 0, 'L' }, { "cs-high", 0, 0, 'C' }, { "3wire", 0, 0, '3' }, + { "no-cs", 0, 0, 'N' }, + { "ready", 0, 0, 'R' }, { NULL, 0, 0, 0 }, }; int c; - c = getopt_long(argc, argv, "D:s:d:b:lHOLC3", lopts, NULL); + c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL); if (c == -1) break; @@ -139,6 +141,12 @@ void parse_opts(int argc, char *argv[]) case '3': mode |= SPI_3WIRE; break; + case 'N': + mode |= SPI_NO_CS; + break; + case 'R': + mode |= SPI_READY; + break; default: print_usage(argv[0]); break; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 5d869c4d3eb2a..606e7a40a8da8 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -58,15 +58,20 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; /* Bit masks for spi_device.mode management. Note that incorrect - * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other - * devices on a shared bus: CS_HIGH, because this device will be - * active when it shouldn't be; 3WIRE, because when active it won't - * behave as it should. + * settings for some settings can cause *lots* of trouble for other + * devices on a shared bus: * - * REVISIT should changing those two modes be privileged? + * - CS_HIGH ... this device will be active when it shouldn't be + * - 3WIRE ... when active, it won't behave as it should + * - NO_CS ... there will be no explicit message boundaries; this + * is completely incompatible with the shared bus model + * - READY ... transfers may proceed when they shouldn't. + * + * REVISIT should changing those flags be privileged? */ #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ - | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP) + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ + | SPI_NO_CS | SPI_READY) struct spidev_data { dev_t devt; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 9c4cd27f46852..743c933ac4e7f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -80,6 +80,8 @@ struct spi_device { #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ #define SPI_3WIRE 0x10 /* SI/SO signals shared */ #define SPI_LOOP 0x20 /* loopback mode */ +#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define SPI_READY 0x80 /* slave pulls low to pause */ u8 bits_per_word; int irq; void *controller_state; diff --git a/include/linux/spi/spidev.h b/include/linux/spi/spidev.h index 95251ccd5a070..bf0570a84f7a4 100644 --- a/include/linux/spi/spidev.h +++ b/include/linux/spi/spidev.h @@ -40,6 +40,8 @@ #define SPI_LSB_FIRST 0x08 #define SPI_3WIRE 0x10 #define SPI_LOOP 0x20 +#define SPI_NO_CS 0x40 +#define SPI_READY 0x80 /*---------------------------------------------------------------------------*/ -- GitLab From 70d6027ff2bc8bab180273b77e7ab3e8a62cca51 Mon Sep 17 00:00:00 2001 From: David Brownell <dbrownell@users.sourceforge.net> Date: Tue, 30 Jun 2009 11:41:27 -0700 Subject: [PATCH 0442/1002] spi: add spi_master flag word Add a new spi_master.flags word listing constraints relevant to that controller. Define the first constraint bit: a half duplex restriction. Include that constraint in the OMAP1 MicroWire controller driver. Have the mmc_spi host be the first customer of this flag. Its coding relies heavily on full duplex transfers, so it must fail when the underlying controller driver won't perform them. (The spi_write_then_read routine could use it too: use the temporarily-withdrawn full-duplex speedup unless this flag is set, in which case the existing code applies. Similarly, any spi_master implementing only SPI_3WIRE should set the flag.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/mmc/host/mmc_spi.c | 6 ++++++ drivers/spi/omap_uwire.c | 2 ++ include/linux/spi/spi.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 240608cc7ae9b..a461017ce5ce9 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1313,6 +1313,12 @@ static int mmc_spi_probe(struct spi_device *spi) struct mmc_spi_host *host; int status; + /* We rely on full duplex transfers, mostly to reduce + * per-transfer overheads (by making fewer transfers). + */ + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) + return -EINVAL; + /* MMC and SD specs only seem to care that sampling is on the * rising edge ... meaning SPI modes 0 or 3. So either SPI mode * should be legit. We'll use mode 0 since the steady state is 0, diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index aa90ddb370662..8980a5640bd9d 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c @@ -514,6 +514,8 @@ static int __init uwire_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->flags = SPI_MASTER_HALF_DUPLEX; + master->bus_num = 2; /* "official" */ master->num_chipselect = 4; master->setup = uwire_setup; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 743c933ac4e7f..c47c4b4da97e5 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -250,6 +250,10 @@ struct spi_master { /* spi_device.mode flags understood by this controller driver */ u16 mode_bits; + /* other constraints relevant to this driver */ + u16 flags; +#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ + /* Setup mode and clock, etc (spi driver may call many times). * * IMPORTANT: this may be called when transfers to another -- GitLab From 537a1bf059fa312355696fa6db80726e655e7f17 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 30 Jun 2009 11:41:29 -0700 Subject: [PATCH 0443/1002] fbdev: add mutex for fb_mmap locking Add a mutex to avoid a circular locking problem between the mm layer semaphore and fbdev ioctl mutex through the fb_mmap() call. Also, add mutex to all places where smem_start and smem_len fields change so the mutex inside the fb_mmap() is actually used. Changing of these fields before calling the framebuffer_register() are not mutexed. This is 2.6.31 material. It removes one lockdep (fb_mmap() and register_framebuffer()) but there is still another one (fb_release() and register_framebuffer()). It also cleans up handling of the smem_start and smem_len fields used by mutexed section of the fb_mmap(). Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: "Rafael J. Wysocki" <rjw@sisk.pl> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/atafb.c | 7 ++++++- drivers/video/atmel_lcdfb.c | 2 ++ drivers/video/fbmem.c | 13 +++++-------- drivers/video/fsl-diu-fb.c | 14 +++++++++----- drivers/video/i810/i810_main.c | 2 ++ drivers/video/matrox/matroxfb_base.c | 3 +++ drivers/video/matrox/matroxfb_crtc2.c | 5 ++++- drivers/video/mx3fb.c | 17 +++++++++++------ drivers/video/omap/omapfb_main.c | 4 ++++ drivers/video/platinumfb.c | 2 ++ drivers/video/pxafb.c | 2 ++ drivers/video/sh7760fb.c | 19 ++++++------------- drivers/video/sis/sis_main.c | 2 ++ drivers/video/sm501fb.c | 21 +++++++++++++-------- drivers/video/w100fb.c | 2 ++ include/linux/fb.h | 1 + 16 files changed, 74 insertions(+), 42 deletions(-) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 018850c116c64..497ff8af03edf 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2414,7 +2414,10 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) if (err) return err; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - return fbhw->encode_fix(fix, &par); + mutex_lock(&info->mm_lock); + err = fbhw->encode_fix(fix, &par); + mutex_unlock(&info->mm_lock); + return err; } static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -2743,7 +2746,9 @@ static int atafb_set_par(struct fb_info *info) /* Decode wanted screen parameters */ fbhw->decode_var(&info->var, par); + mutex_lock(&info->mm_lock); fbhw->encode_fix(&info->fix, par); + mutex_unlock(&info->mm_lock); /* Set new videomode */ ata_set_par(par); diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5afd64482f558..cb88394ba9952 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -270,7 +270,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) smem_len = (var->xres_virtual * var->yres_virtual * ((var->bits_per_pixel + 7) / 8)); + mutex_lock(&info->mm_lock); info->fix.smem_len = max(smem_len, sinfo->smem_len); + mutex_unlock(&info->mm_lock); info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index f8a09bf8d0cde..53ea05645ff8e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1310,8 +1310,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, static int fb_mmap(struct file *file, struct vm_area_struct * vma) -__acquires(&info->lock) -__releases(&info->lock) { int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; @@ -1325,16 +1323,14 @@ __releases(&info->lock) off = vma->vm_pgoff << PAGE_SHIFT; if (!fb) return -ENODEV; + mutex_lock(&info->mm_lock); if (fb->fb_mmap) { int res; - mutex_lock(&info->lock); res = fb->fb_mmap(info, vma); - mutex_unlock(&info->lock); + mutex_unlock(&info->mm_lock); return res; } - mutex_lock(&info->lock); - /* frame buffer memory */ start = info->fix.smem_start; len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); @@ -1342,13 +1338,13 @@ __releases(&info->lock) /* memory mapped io */ off -= len; if (info->var.accel_flags) { - mutex_unlock(&info->lock); + mutex_unlock(&info->mm_lock); return -EINVAL; } start = info->fix.mmio_start; len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); } - mutex_unlock(&info->lock); + mutex_unlock(&info->mm_lock); start &= PAGE_MASK; if ((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; @@ -1518,6 +1514,7 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = i; mutex_init(&fb_info->lock); + mutex_init(&fb_info->mm_lock); fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index f153c581cbd7b..0bf2190928d0e 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info) static int map_video_memory(struct fb_info *info) { phys_addr_t phys; + u32 smem_len = info->fix.line_length * info->var.yres_virtual; pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); pr_debug("info->fix.line_length = %d\n", info->fix.line_length); + pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); - info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; - pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); - info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); + info->screen_base = fsl_diu_alloc(smem_len, &phys); if (info->screen_base == NULL) { printk(KERN_ERR "Unable to allocate fb memory\n"); return -ENOMEM; } + mutex_lock(&info->mm_lock); info->fix.smem_start = (unsigned long) phys; + info->fix.smem_len = smem_len; + mutex_unlock(&info->mm_lock); info->screen_size = info->fix.smem_len; pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", - info->fix.smem_start, - info->fix.smem_len); + info->fix.smem_start, info->fix.smem_len); pr_debug("screen base %p\n", info->screen_base); return 0; @@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info) static void unmap_video_memory(struct fb_info *info) { fsl_diu_free(info->screen_base, info->fix.smem_len); + mutex_lock(&info->mm_lock); info->screen_base = NULL; info->fix.smem_start = 0; info->fix.smem_len = 0; + mutex_unlock(&info->mm_lock); } /* diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 2e940199fc892..71960672d7214 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, "I810"); + mutex_lock(&info->mm_lock); fix->smem_start = par->fb.physical; fix->smem_len = par->fb.size; + mutex_unlock(&info->mm_lock); fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->xpanstep = 8; diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 8e7a275df50c7..59c3a2e149137 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2) struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; DBG(__func__) + mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock); fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); + mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock); } static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -2081,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm spin_lock_init(&ACCESS_FBINFO(lock.accel)); init_rwsem(&ACCESS_FBINFO(crtc2.lock)); init_rwsem(&ACCESS_FBINFO(altout.lock)); + mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); ACCESS_FBINFO(irq_flags) = 0; init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 7ac4c5f6145d0..909e10a11898b 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -289,13 +289,16 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { #undef m2info } -static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { +static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) +{ struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; strcpy(fix->id, "MATROX DH"); + mutex_lock(&m2info->fbcon.mm_lock); fix->smem_start = m2info->video.base; fix->smem_len = m2info->video.len_usable; + mutex_unlock(&m2info->fbcon.mm_lock); fix->ypanstep = 1; fix->ywrapstep = 0; fix->xpanstep = 8; /* TBD */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index b7af5256e887e..567fb944bd2ae 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp) } static int mx3fb_blank(int blank, struct fb_info *fbi); -static int mx3fb_map_video_memory(struct fb_info *fbi); +static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len); static int mx3fb_unmap_video_memory(struct fb_info *fbi); /** @@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi) if (fbi->fix.smem_start) mx3fb_unmap_video_memory(fbi); - fbi->fix.smem_len = mem_len; - if (mx3fb_map_video_memory(fbi) < 0) { + if (mx3fb_map_video_memory(fbi, mem_len) < 0) { mutex_unlock(&mx3_fbi->mutex); return -ENOMEM; } @@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev) /** * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. * @fbi: framebuffer information pointer + * @mem_len: length of mapped memory * @return: Error code indicating success or failure * * This buffer is remapped into a non-cached, non-buffered, memory region to @@ -1205,23 +1205,26 @@ static int mx3fb_resume(struct platform_device *pdev) * area is remapped, all virtual memory access to the video memory should occur * at the new region. */ -static int mx3fb_map_video_memory(struct fb_info *fbi) +static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) { int retval = 0; dma_addr_t addr; fbi->screen_base = dma_alloc_writecombine(fbi->device, - fbi->fix.smem_len, + mem_len, &addr, GFP_DMA); if (!fbi->screen_base) { dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", - fbi->fix.smem_len); + mem_len); retval = -EBUSY; goto err0; } + mutex_lock(&fbi->mm_lock); fbi->fix.smem_start = addr; + fbi->fix.smem_len = mem_len; + mutex_unlock(&fbi->mm_lock); dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); @@ -1251,8 +1254,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi) fbi->screen_base, fbi->fix.smem_start); fbi->screen_base = 0; + mutex_lock(&fbi->mm_lock); fbi->fix.smem_start = 0; fbi->fix.smem_len = 0; + mutex_unlock(&fbi->mm_lock); return 0; } diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 060d72fe57cb1..4ea99bfc37b48 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi) rg = &plane->fbdev->mem_desc.region[plane->idx]; fbi->screen_base = rg->vaddr; + mutex_lock(&fbi->mm_lock); fix->smem_start = rg->paddr; fix->smem_len = rg->size; + mutex_unlock(&fbi->mm_lock); fix->type = FB_TYPE_PACKED_PIXELS; bpp = var->bits_per_pixel; @@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) * plane memory is dealloce'd, the other * screen parameters in var / fix are invalid. */ + mutex_lock(&fbi->mm_lock); fbi->fix.smem_start = 0; fbi->fix.smem_len = 0; + mutex_unlock(&fbi->mm_lock); } } } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 03b3670130a0d..bacfabd9ce165 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info) offset = 0x10; info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; + mutex_lock(&info->mm_lock); info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; + mutex_unlock(&info->mm_lock); info->fix.visual = (pinfo->cmode == CMODE_8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0889d50c3288e..6506117c134ba 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) ofb->video_mem_phys = virt_to_phys(ofb->video_mem); ofb->video_mem_size = size; + mutex_lock(&ofb->fb.mm_lock); ofb->fb.fix.smem_start = ofb->video_mem_phys; ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; + mutex_unlock(&ofb->fb.mm_lock); ofb->fb.screen_base = ofb->video_mem; return 0; } diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index 653bdfee30578..9f6d6e61f0cc7 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c @@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno, return 0; } -static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info, - unsigned long stride) -{ - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, "sh7760-lcdc"); - - fix->smem_start = (unsigned long)info->screen_base; - fix->smem_len = info->screen_size; - - fix->line_length = stride; -} - static int sh7760fb_get_color_info(struct device *dev, u16 lddfr, int *bpp, int *gray) { @@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info) iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ - encode_fix(&info->fix, info, stride); + info->fix.line_length = stride; + sh7760fb_check_var(&info->var, info); sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ @@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info) info->screen_base = fbmem; info->screen_size = vram; + info->fix.smem_start = (unsigned long)info->screen_base; + info->fix.smem_len = info->screen_size; return 0; } @@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) info->var.transp.length = 0; info->var.transp.msb_right = 0; + strcpy(info->fix.id, "sh7760-lcdc"); + /* set the DON2 bit now, before cmap allocation, as it will randomize * palette memory. */ diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 7072d19080d58..fd33455389b89 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) strcpy(fix->id, ivideo->myid); + mutex_lock(&info->mm_lock); fix->smem_start = ivideo->video_base + ivideo->video_offset; fix->smem_len = ivideo->sisfb_mem; + mutex_unlock(&info->mm_lock); fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index eb5d73a067024..98f24f0ec00df 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) #define SM501_MEMF_ACCEL (8) static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, - unsigned int why, size_t size) + unsigned int why, size_t size, u32 smem_len) { struct sm501fb_par *par; struct fb_info *fbi; @@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, if (ptr > 0) ptr &= ~(PAGE_SIZE - 1); - if (fbi && ptr < fbi->fix.smem_len) + if (fbi && ptr < smem_len) return -ENOMEM; break; @@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, case SM501_MEMF_ACCEL: fbi = inf->fb[HEAD_CRT]; - ptr = fbi ? fbi->fix.smem_len : 0; + ptr = fbi ? smem_len : 0; fbi = inf->fb[HEAD_PANEL]; if (fbi) { @@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info, unsigned int mem_type; unsigned int clock_type; unsigned int head_addr; + unsigned int smem_len; dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", __func__, var->xres, var->yres, var->bits_per_pixel, @@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info, /* allocate fb memory within 501 */ info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; - info->fix.smem_len = info->fix.line_length * var->yres_virtual; + smem_len = info->fix.line_length * var->yres_virtual; dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, info->fix.line_length); - if (sm501_alloc_mem(fbi, &par->screen, mem_type, - info->fix.smem_len)) { + if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) { dev_err(fbi->dev, "no memory available\n"); return -ENOMEM; } + mutex_lock(&info->mm_lock); info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; + info->fix.smem_len = smem_len; + mutex_unlock(&info->mm_lock); info->screen_base = fbi->fbmem + par->screen.sm_addr; info->screen_size = info->fix.smem_len; @@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info) if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { /* the head is displaying panel data... */ - sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); + sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0, + info->fix.smem_len); goto out_update; } @@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) par->cursor_regs = info->regs + reg_base; - ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); + ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024, + fbi->fix.smem_len); if (ret < 0) return ret; diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index d0674f1e3f108..8a141c2c637bf 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info) info->fix.ywrapstep = 0; info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; + mutex_lock(&info->mm_lock); if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { par->extmem_active = 1; info->fix.smem_len = par->mach->mem->size+1; @@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info) par->extmem_active = 0; info->fix.smem_len = MEM_INT_SIZE+1; } + mutex_unlock(&info->mm_lock); w100fb_activate_var(par); } diff --git a/include/linux/fb.h b/include/linux/fb.h index dd68358996b71..f847df9e99b6f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -819,6 +819,7 @@ struct fb_info { int node; int flags; struct mutex lock; /* Lock for open/release/ioctl funcs */ + struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ struct fb_var_screeninfo var; /* Current var */ struct fb_fix_screeninfo fix; /* Current fix */ struct fb_monspecs monspecs; /* Current Monitor specs */ -- GitLab From 529ba0d9669386157457a1cb96294d2fe79b3f88 Mon Sep 17 00:00:00 2001 From: David Brownell <dbrownell@users.sourceforge.net> Date: Tue, 30 Jun 2009 11:41:30 -0700 Subject: [PATCH 0444/1002] spi: bitbang bugfix in message setup Bugfix to spi_bitbang infrastructure: make sure to always set transfer parameters on the first pass through the message's per-transfer loop. This can matter with drivers that replace the per-word or per-buffer transfer primitives, on busses with multiple SPI devices. Previously, this could have started messages using the settings left after previous messages. The problem was observed when a high speed chip (m25p80 type flash) was running very slowly because a low speed device (avr8 microcontroller) had previously used the bus. Similar faults could have driven the low speed device too fast, or used an unexpected word size. Acked-by: Steven A. Falco <sfalco@harris.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/spi/spi_bitbang.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 2a5abc08e8571..f1db395dd8898 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -258,6 +258,11 @@ static void bitbang_work(struct work_struct *work) struct spi_bitbang *bitbang = container_of(work, struct spi_bitbang, work); unsigned long flags; + int do_setup = -1; + int (*setup_transfer)(struct spi_device *, + struct spi_transfer *); + + setup_transfer = bitbang->setup_transfer; spin_lock_irqsave(&bitbang->lock, flags); bitbang->busy = 1; @@ -269,8 +274,6 @@ static void bitbang_work(struct work_struct *work) unsigned tmp; unsigned cs_change; int status; - int (*setup_transfer)(struct spi_device *, - struct spi_transfer *); m = container_of(bitbang->queue.next, struct spi_message, queue); @@ -287,19 +290,19 @@ static void bitbang_work(struct work_struct *work) tmp = 0; cs_change = 1; status = 0; - setup_transfer = NULL; list_for_each_entry (t, &m->transfers, transfer_list) { - /* override or restore speed and wordsize */ - if (t->speed_hz || t->bits_per_word) { - setup_transfer = bitbang->setup_transfer; + /* override speed or wordsize? */ + if (t->speed_hz || t->bits_per_word) + do_setup = 1; + + /* init (-1) or override (1) transfer params */ + if (do_setup != 0) { if (!setup_transfer) { status = -ENOPROTOOPT; break; } - } - if (setup_transfer) { status = setup_transfer(spi, t); if (status < 0) break; @@ -363,9 +366,10 @@ static void bitbang_work(struct work_struct *work) m->status = status; m->complete(m->context); - /* restore speed and wordsize */ - if (setup_transfer) + /* restore speed and wordsize if it was overridden */ + if (do_setup == 1) setup_transfer(spi, NULL); + do_setup = 0; /* normally deactivate chipselect ... unless no error and * cs_change has hinted that the next message will probably -- GitLab From 8bc1ad7dd301b7ca7454013519fa92e8c53655ff Mon Sep 17 00:00:00 2001 From: Zhang Rui <rui.zhang@intel.com> Date: Tue, 30 Jun 2009 11:41:31 -0700 Subject: [PATCH 0445/1002] kernel/resource.c: fix sign extension in reserve_setup() When the 32-bit signed quantities get assigned to the u64 resource_size_t, they are incorrectly sign-extended. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13253 Addresses http://bugzilla.kernel.org/show_bug.cgi?id=9905 Signed-off-by: Zhang Rui <rui.zhang@intel.com> Reported-by: Leann Ogasawara <leann@ubuntu.com> Cc: Pierre Ossman <drzeus@drzeus.cx> Reported-by: <pablomme@googlemail.com> Tested-by: <pablomme@googlemail.com> Cc: <stable@kernel.org> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/resource.c b/kernel/resource.c index ac5f3a36923fc..78b087221c156 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -787,7 +787,7 @@ static int __init reserve_setup(char *str) static struct resource reserve[MAXRESERVE]; for (;;) { - int io_start, io_num; + unsigned int io_start, io_num; int x = reserved; if (get_option (&str, &io_start) != 2) -- GitLab From b4f90189dc2c7a7e6926ea480ae3404ec3de4581 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Tue, 30 Jun 2009 11:41:32 -0700 Subject: [PATCH 0446/1002] MAINTAINERS: STARFIRE/DURALAN update Ion's cs.columbia.edu email address no longer works. Signed-off-by: Joe Perches <joe@perches.com> Acked-by: Ion Badulescu <ionut@badula.org> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 92fe0796cd1b6..6a89e312a7b4e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5576,8 +5576,8 @@ F: drivers/staging/ STARFIRE/DURALAN NETWORK DRIVER P: Ion Badulescu -M: ionut@cs.columbia.edu -S: Maintained +M: ionut@badula.org +S: Odd Fixes F: drivers/net/starfire* STARMODE RADIO IP (STRIP) PROTOCOL DRIVER -- GitLab From df279ca8966c3de83105428e3391ab17690802a9 Mon Sep 17 00:00:00 2001 From: Renaud Lottiaux <renaud.lottiaux@kerlabs.com> Date: Tue, 30 Jun 2009 11:41:34 -0700 Subject: [PATCH 0447/1002] bsdacct: fix access to invalid filp in acct_on() The file opened in acct_on and freshly stored in the ns->bacct struct can be closed in acct_file_reopen by a concurrent call after we release acct_lock and before we call mntput(file->f_path.mnt). Record file->f_path.mnt in a local variable and use this variable only. Signed-off-by: Renaud Lottiaux <renaud.lottiaux@kerlabs.com> Signed-off-by: Louis Rilling <louis.rilling@kerlabs.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- kernel/acct.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/acct.c b/kernel/acct.c index 7afa31564162d..9f3391090b3e8 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -215,6 +215,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, static int acct_on(char *name) { struct file *file; + struct vfsmount *mnt; int error; struct pid_namespace *ns; struct bsd_acct_struct *acct = NULL; @@ -256,11 +257,12 @@ static int acct_on(char *name) acct = NULL; } - mnt_pin(file->f_path.mnt); + mnt = file->f_path.mnt; + mnt_pin(mnt); acct_file_reopen(ns->bacct, file, ns); spin_unlock(&acct_lock); - mntput(file->f_path.mnt); /* it's pinned, now give up active reference */ + mntput(mnt); /* it's pinned, now give up active reference */ kfree(acct); return 0; -- GitLab From d7831a0bdf06b9f722b947bb0c205ff7d77cebd8 Mon Sep 17 00:00:00 2001 From: Richard Kennedy <richard@rsk.demon.co.uk> Date: Tue, 30 Jun 2009 11:41:35 -0700 Subject: [PATCH 0448/1002] mm: prevent balance_dirty_pages() from doing too much work balance_dirty_pages can overreact and move all of the dirty pages to writeback unnecessarily. balance_dirty_pages makes its decision to throttle based on the number of dirty plus writeback pages that are over the calculated limit,so it will continue to move pages even when there are plenty of pages in writeback and less than the threshold still dirty. This allows it to overshoot its limits and move all the dirty pages to writeback while waiting for the drives to catch up and empty the writeback list. A simple fio test easily demonstrates this problem. fio --name=f1 --directory=/disk1 --size=2G -rw=write --name=f2 --directory=/disk2 --size=1G --rw=write --startdelay=10 This is the simplest fix I could find, but I'm not entirely sure that it alone will be enough for all cases. But it certainly is an improvement on my desktop machine writing to 2 disks. Do we need something more for machines with large arrays where bdi_threshold * number_of_drives is greater than the dirty_ratio ? Signed-off-by: Richard Kennedy <richard@rsk.demon.co.uk> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/page-writeback.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 7b0dcea4935be..7687879253b92 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -541,8 +541,11 @@ static void balance_dirty_pages(struct address_space *mapping) * filesystems (i.e. NFS) in which data may have been * written to the server's write cache, but has not yet * been flushed to permanent storage. + * Only move pages to writeback if this bdi is over its + * threshold otherwise wait until the disk writes catch + * up. */ - if (bdi_nr_reclaimable) { + if (bdi_nr_reclaimable > bdi_thresh) { writeback_inodes(&wbc); pages_written += write_chunk - wbc.nr_to_write; get_dirty_limits(&background_thresh, &dirty_thresh, -- GitLab From b37f2d4de6dfce4bfd6df311af80e4d61458ee1e Mon Sep 17 00:00:00 2001 From: Nikanth Karthikesan <knikanth@suse.de> Date: Tue, 30 Jun 2009 11:41:36 -0700 Subject: [PATCH 0449/1002] cpusets: document adding/removing cpus to cpuset elaborately By writing a tasks's pid to the file, a process adds that task to that cgroup/cpuset. But to add a cpu/mem to a cpuset, the new list of cpus should be written to the cpuset.mems file which would replace the old list of cpus. Make this clearer in the documentation. Signed-off-by: Nikanth Karthikesan <knikanth@suse.de> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Acked-by: Paul Menage <menage@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/cgroups/cpusets.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt index f9ca389dddf49..1d7e9784439ad 100644 --- a/Documentation/cgroups/cpusets.txt +++ b/Documentation/cgroups/cpusets.txt @@ -777,6 +777,18 @@ in cpuset directories: # /bin/echo 1-4 > cpus -> set cpus list to cpus 1,2,3,4 # /bin/echo 1,2,3,4 > cpus -> set cpus list to cpus 1,2,3,4 +To add a CPU to a cpuset, write the new list of CPUs including the +CPU to be added. To add 6 to the above cpuset: + +# /bin/echo 1-4,6 > cpus -> set cpus list to cpus 1,2,3,4,6 + +Similarly to remove a CPU from a cpuset, write the new list of CPUs +without the CPU to be removed. + +To remove all the CPUs: + +# /bin/echo "" > cpus -> clear cpus list + 2.3 Setting flags ----------------- -- GitLab From 66918dcdf91ad101194c749c18099e836ba3de2b Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Tue, 30 Jun 2009 11:41:37 -0700 Subject: [PATCH 0450/1002] x86: only clear node_states for 64bit Nathan reported that | commit 73d60b7f747176dbdff826c4127d22e1fd3f9f74 | Author: Yinghai Lu <yinghai@kernel.org> | Date: Tue Jun 16 15:33:00 2009 -0700 | | page-allocator: clear N_HIGH_MEMORY map before we set it again | | SRAT tables may contains nodes of very small size. The arch code may | decide to not activate such a node. However, currently the early boot | code sets N_HIGH_MEMORY for such nodes. These nodes therefore seem to be | active although these nodes have no present pages. | | For 64bit N_HIGH_MEMORY == N_NORMAL_MEMORY, so that works for 64 bit too unintentionally and incorrectly clears the cpuset.mems cgroup attribute on an i386 kvm guest, meaning that cpuset.mems can not be used. Fix this by only clearing node_states[N_NORMAL_MEMORY] for 64bit only. and need to do save/restore for that in find_zone_movable_pfn Reported-by: Nathan Lynch <ntl@pobox.com> Tested-by: Nathan Lynch <ntl@pobox.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Christoph Lameter <cl@linux-foundation.org> Cc: Ingo Molnar <mingo@elte.hu>, Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/mm/init_64.c | 2 ++ mm/page_alloc.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index c4378f4fd4a5e..b177652251a43 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -598,6 +598,8 @@ void __init paging_init(void) sparse_memory_present_with_active_regions(MAX_NUMNODES); sparse_init(); + /* clear the default setting with node 0 */ + nodes_clear(node_states[N_NORMAL_MEMORY]); free_area_init_nodes(max_zone_pfns); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5d714f8fb3033..e0f2cdf9d8b1f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4032,6 +4032,8 @@ static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn) int i, nid; unsigned long usable_startpfn; unsigned long kernelcore_node, kernelcore_remaining; + /* save the state before borrow the nodemask */ + nodemask_t saved_node_state = node_states[N_HIGH_MEMORY]; unsigned long totalpages = early_calculate_totalpages(); int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]); @@ -4059,7 +4061,7 @@ static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn) /* If kernelcore was not specified, there is no ZONE_MOVABLE */ if (!required_kernelcore) - return; + goto out; /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */ find_usable_zone_for_movable(); @@ -4158,6 +4160,10 @@ static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn) for (nid = 0; nid < MAX_NUMNODES; nid++) zone_movable_pfn[nid] = roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES); + +out: + /* restore the node_state */ + node_states[N_HIGH_MEMORY] = saved_node_state; } /* Any regular memory on that node ? */ @@ -4242,11 +4248,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) early_node_map[i].start_pfn, early_node_map[i].end_pfn); - /* - * find_zone_movable_pfns_for_nodes/early_calculate_totalpages init - * that node_mask, clear it at first - */ - nodes_clear(node_states[N_HIGH_MEMORY]); /* Initialise every node */ mminit_verify_pageflags_layout(); setup_nr_node_ids(); -- GitLab From 79d7f4ee23d41571d9e4663521b5e6604c55729a Mon Sep 17 00:00:00 2001 From: Baruch Siach <baruch@tkos.co.il> Date: Tue, 30 Jun 2009 11:41:38 -0700 Subject: [PATCH 0451/1002] gpio: pl061: fix probe error handling code Note that IRQ has not been initialized when kmalloc() fails. Also, use DECLARE_BITMAP() to make the code clearer. Signed-off-by: Baruch Siach <baruch@tkos.co.il> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/gpio/pl061.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index aa8e7cb020d93..80e4839866991 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -221,7 +221,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) struct pl061_gpio *chip; struct list_head *chip_list; int ret, irq, i; - static unsigned long init_irq[BITS_TO_LONGS(NR_IRQS)]; + static DECLARE_BITMAP(init_irq, NR_IRQS); pdata = dev->dev.platform_data; if (pdata == NULL) @@ -280,6 +280,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); if (chip_list == NULL) { + clear_bit(irq, init_irq); ret = -ENOMEM; goto iounmap; } -- GitLab From 50efacf6711e6c75595afd9b92aa15c1e4f7c79d Mon Sep 17 00:00:00 2001 From: Baruch Siach <baruch@tkos.co.il> Date: Tue, 30 Jun 2009 11:41:39 -0700 Subject: [PATCH 0452/1002] gpio: pl061: fix IRQ handling for GPIOs >= PL061_GPIO_NR IRQ handling is wrong for any GPIO >= PL061_GPIO_NR. Fix this by implementing and using a proper .to_irq method. Signed-off-by: Baruch Siach <baruch@tkos.co.il> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/gpio/pl061.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 80e4839866991..4ee4c8367a3f9 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -109,6 +109,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) writeb(!!value << offset, chip->base + (1 << (offset + 2))); } +static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) +{ + struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); + + if (chip->irq_base == (unsigned) -1) + return -EINVAL; + + return chip->irq_base + offset; +} + /* * PL061 GPIO IRQ */ @@ -200,7 +210,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) desc->chip->ack(irq); list_for_each(ptr, chip_list) { unsigned long pending; - int gpio; + int offset; chip = list_entry(ptr, struct pl061_gpio, list); pending = readb(chip->base + GPIOMIS); @@ -209,8 +219,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) if (pending == 0) continue; - for_each_bit(gpio, &pending, PL061_GPIO_NR) - generic_handle_irq(gpio_to_irq(gpio)); + for_each_bit(offset, &pending, PL061_GPIO_NR) + generic_handle_irq(pl061_to_irq(&chip->gc, offset)); } desc->chip->unmask(irq); } @@ -251,6 +261,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id) chip->gc.direction_output = pl061_direction_output; chip->gc.get = pl061_get_value; chip->gc.set = pl061_set_value; + chip->gc.to_irq = pl061_to_irq; chip->gc.base = pdata->gpio_base; chip->gc.ngpio = PL061_GPIO_NR; chip->gc.label = dev_name(&dev->dev); -- GitLab From eafad22a05fdaca60f06433ffe8810aaa920d539 Mon Sep 17 00:00:00 2001 From: Ville Syrjala <syrjala@sci.fi> Date: Tue, 30 Jun 2009 11:41:40 -0700 Subject: [PATCH 0453/1002] atyfb: fix HP OmniBook 500 reboot hang Apparently HP OmniBook 500's BIOS doesn't like the way atyfb reprograms the hardware. The BIOS will simply hang after a reboot. Fix the problem by restoring the hardware to it's original state on reboot. Signed-off-by: Ville Syrjala <syrjala@sci.fi> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/aty/atyfb.h | 2 + drivers/video/aty/atyfb_base.c | 89 ++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 7691e73823d39..0369653b5d883 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -187,6 +187,8 @@ struct atyfb_par { int mtrr_reg; #endif u32 mem_cntl; + struct crtc saved_crtc; + union aty_pll saved_pll; }; /* diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 1207c208a30b3..06782906daf54 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -66,6 +66,8 @@ #include <linux/spinlock.h> #include <linux/wait.h> #include <linux/backlight.h> +#include <linux/reboot.h> +#include <linux/dmi.h> #include <asm/io.h> #include <linux/uaccess.h> @@ -249,8 +251,6 @@ static int aty_init(struct fb_info *info); static int store_video_par(char *videopar, unsigned char m64_num); #endif -static struct crtc saved_crtc; -static union aty_pll saved_pll; static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); @@ -261,6 +261,8 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); static int read_aty_sense(const struct atyfb_par *par); #endif +static DEFINE_MUTEX(reboot_lock); +static struct fb_info *reboot_info; /* * Interface used by the world @@ -2390,9 +2392,9 @@ static int __devinit aty_init(struct fb_info *info) #endif /* CONFIG_FB_ATY_CT */ /* save previous video mode */ - aty_get_crtc(par, &saved_crtc); + aty_get_crtc(par, &par->saved_crtc); if(par->pll_ops->get_pll) - par->pll_ops->get_pll(info, &saved_pll); + par->pll_ops->get_pll(info, &par->saved_pll); par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); @@ -2667,8 +2669,8 @@ static int __devinit aty_init(struct fb_info *info) aty_init_exit: /* restore video mode */ - aty_set_crtc(par, &saved_crtc); - par->pll_ops->set_pll(info, &saved_pll); + aty_set_crtc(par, &par->saved_crtc); + par->pll_ops->set_pll(info, &par->saved_pll); #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { @@ -3502,6 +3504,11 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi par->mmap_map[1].prot_flag = _PAGE_E; #endif /* __sparc__ */ + mutex_lock(&reboot_lock); + if (!reboot_info) + reboot_info = info; + mutex_unlock(&reboot_lock); + return 0; err_release_io: @@ -3614,8 +3621,8 @@ static void __devexit atyfb_remove(struct fb_info *info) struct atyfb_par *par = (struct atyfb_par *) info->par; /* restore video mode */ - aty_set_crtc(par, &saved_crtc); - par->pll_ops->set_pll(info, &saved_pll); + aty_set_crtc(par, &par->saved_crtc); + par->pll_ops->set_pll(info, &par->saved_pll); unregister_framebuffer(info); @@ -3661,6 +3668,11 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); + mutex_lock(&reboot_lock); + if (reboot_info == info) + reboot_info = NULL; + mutex_unlock(&reboot_lock); + atyfb_remove(info); } @@ -3808,6 +3820,56 @@ static int __init atyfb_setup(char *options) } #endif /* MODULE */ +static int atyfb_reboot_notify(struct notifier_block *nb, + unsigned long code, void *unused) +{ + struct atyfb_par *par; + + if (code != SYS_RESTART) + return NOTIFY_DONE; + + mutex_lock(&reboot_lock); + + if (!reboot_info) + goto out; + + if (!lock_fb_info(reboot_info)) + goto out; + + par = reboot_info->par; + + /* + * HP OmniBook 500's BIOS doesn't like the state of the + * hardware after atyfb has been used. Restore the hardware + * to the original state to allow successful reboots. + */ + aty_set_crtc(par, &par->saved_crtc); + par->pll_ops->set_pll(reboot_info, &par->saved_pll); + + unlock_fb_info(reboot_info); + out: + mutex_unlock(&reboot_lock); + + return NOTIFY_DONE; +} + +static struct notifier_block atyfb_reboot_notifier = { + .notifier_call = atyfb_reboot_notify, +}; + +static const struct dmi_system_id atyfb_reboot_ids[] = { + { + .ident = "HP OmniBook 500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"), + }, + }, + + { } +}; + static int __init atyfb_init(void) { int err1 = 1, err2 = 1; @@ -3826,11 +3888,20 @@ static int __init atyfb_init(void) err2 = atyfb_atari_probe(); #endif - return (err1 && err2) ? -ENODEV : 0; + if (err1 && err2) + return -ENODEV; + + if (dmi_check_system(atyfb_reboot_ids)) + register_reboot_notifier(&atyfb_reboot_notifier); + + return 0; } static void __exit atyfb_exit(void) { + if (dmi_check_system(atyfb_reboot_ids)) + unregister_reboot_notifier(&atyfb_reboot_notifier); + #ifdef CONFIG_PCI pci_unregister_driver(&atyfb_driver); #endif -- GitLab From ee905d0c58a440a5bd10c845e8305f6f7f706be2 Mon Sep 17 00:00:00 2001 From: Ville Syrjala <syrjala@sci.fi> Date: Tue, 30 Jun 2009 11:41:42 -0700 Subject: [PATCH 0454/1002] atyfb: fix alignment for block writes Block writes require 64 byte alignment. Since block writes could be used with SGRAM or WRAM also refine the memory type detection to check for either type before deciding to use the 64 byte alignment. Signed-off-by: Ville Syrjala <syrjala@sci.fi> Tested-by: Mikulas Patocka <mpatocka@redhat.com> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/aty/atyfb.h | 1 + drivers/video/aty/atyfb_base.c | 52 ++++++++++++++++++++++++-------- drivers/video/aty/mach64_accel.c | 7 +++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index 0369653b5d883..1f39a62f899be 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -219,6 +219,7 @@ struct atyfb_par { #define M64F_XL_DLL 0x00080000 #define M64F_MFB_FORCE_4 0x00100000 #define M64F_HW_TRIPLE 0x00200000 +#define M64F_XL_MEM 0x00400000 /* * Register access */ diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 06782906daf54..63d3739d43a85 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -363,8 +363,8 @@ static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, }; #define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) #define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) -#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4) -#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS) +#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM) +#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS) static struct { u16 pci_id; @@ -541,6 +541,7 @@ static char ram_edo[] __devinitdata = "EDO"; static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; +static char ram_wram[] __devinitdata = "WRAM"; static char ram_off[] __devinitdata = "OFF"; #endif /* CONFIG_FB_ATY_CT */ @@ -554,6 +555,10 @@ static char *aty_gx_ram[8] __devinitdata = { #ifdef CONFIG_FB_ATY_CT static char *aty_ct_ram[8] __devinitdata = { + ram_off, ram_dram, ram_edo, ram_edo, + ram_sdram, ram_sgram, ram_wram, ram_resv +}; +static char *aty_xl_ram[8] __devinitdata = { ram_off, ram_dram, ram_edo, ram_edo, ram_sdram, ram_sgram, ram_sdram32, ram_resv }; @@ -762,6 +767,17 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) #endif /* CONFIG_FB_ATY_GENERIC_LCD */ } +static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp) +{ + u32 line_length = vxres * bpp / 8; + + if (par->ram_type == SGRAM || + (!M64_HAS(XL_MEM) && par->ram_type == WRAM)) + line_length = (line_length + 63) & ~63; + + return line_length; +} + static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc) { @@ -771,13 +787,14 @@ static int aty_var_to_crtc(const struct fb_info *info, u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; u32 pix_width, dp_pix_width, dp_chain_mask; + u32 line_length; /* input */ - xres = var->xres; + xres = (var->xres + 7) & ~7; yres = var->yres; - vxres = var->xres_virtual; + vxres = (var->xres_virtual + 7) & ~7; vyres = var->yres_virtual; - xoffset = var->xoffset; + xoffset = (var->xoffset + 7) & ~7; yoffset = var->yoffset; bpp = var->bits_per_pixel; if (bpp == 16) @@ -829,7 +846,9 @@ static int aty_var_to_crtc(const struct fb_info *info, } else FAIL("invalid bpp"); - if (vxres * vyres * bpp / 8 > info->fix.smem_len) + line_length = calc_line_length(par, vxres, bpp); + + if (vyres * line_length > info->fix.smem_len) FAIL("not enough video RAM"); h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; @@ -971,7 +990,9 @@ static int aty_var_to_crtc(const struct fb_info *info, crtc->xoffset = xoffset; crtc->yoffset = yoffset; crtc->bpp = bpp; - crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); + crtc->off_pitch = + ((yoffset * line_length + xoffset * bpp / 8) / 8) | + ((line_length / bpp) << 22); crtc->vline_crnt_vline = 0; crtc->h_tot_disp = h_total | (h_disp<<16); @@ -1396,7 +1417,9 @@ static int atyfb_set_par(struct fb_info *info) } aty_st_8(DAC_MASK, 0xff, par); - info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8; + info->fix.line_length = calc_line_length(par, var->xres_virtual, + var->bits_per_pixel); + info->fix.visual = var->bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; @@ -1507,10 +1530,12 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info) { u32 xoffset = info->var.xoffset; u32 yoffset = info->var.yoffset; - u32 vxres = par->crtc.vxres; + u32 line_length = info->fix.line_length; u32 bpp = info->var.bits_per_pixel; - par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19); + par->crtc.off_pitch = + ((yoffset * line_length + xoffset * bpp / 8) / 8) | + ((line_length / bpp) << 22); } @@ -2203,7 +2228,7 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) const int *refresh_tbl; int i, size; - if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { + if (M64_HAS(XL_MEM)) { refresh_tbl = ragexl_tbl; size = ARRAY_SIZE(ragexl_tbl); } else { @@ -2337,7 +2362,10 @@ static int __devinit aty_init(struct fb_info *info) par->pll_ops = &aty_pll_ct; par->bus_type = PCI; par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); - ramname = aty_ct_ram[par->ram_type]; + if (M64_HAS(XL_MEM)) + ramname = aty_xl_ram[par->ram_type]; + else + ramname = aty_ct_ram[par->ram_type]; /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) par->pll_limits.mclk = 63; diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index 0cc9724e61a26..51fcc0a2c94a9 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c @@ -63,14 +63,17 @@ static void reset_GTC_3D_engine(const struct atyfb_par *par) void aty_init_engine(struct atyfb_par *par, struct fb_info *info) { u32 pitch_value; + u32 vxres; /* determine modal information from global mode structure */ - pitch_value = info->var.xres_virtual; + pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8); + vxres = info->var.xres_virtual; if (info->var.bits_per_pixel == 24) { /* In 24 bpp, the engine is in 8 bpp - this requires that all */ /* horizontal coordinates and widths must be adjusted */ pitch_value *= 3; + vxres *= 3; } /* On GTC (RagePro), we need to reset the 3D engine before */ @@ -133,7 +136,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info) aty_st_le32(SC_LEFT, 0, par); aty_st_le32(SC_TOP, 0, par); aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); - aty_st_le32(SC_RIGHT, pitch_value - 1, par); + aty_st_le32(SC_RIGHT, vxres - 1, par); /* set background color to minimum value (usually BLACK) */ aty_st_le32(DP_BKGD_CLR, 0, par); -- GitLab From 9980060bad5607ca6db7fb8683de671b522e56a4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger <vapier@gentoo.org> Date: Tue, 30 Jun 2009 11:41:43 -0700 Subject: [PATCH 0455/1002] bfin: delay IRQ registration until driver is ready Make sure we do not actually request the RTC IRQ until the device driver is fully ready to handle and process any interrupt. This way a spurious interrupt won't crash the system (which may happen if the bootloader was poking the RTC right before booting Linux). Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-bfin.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index aafd3e6ebb0df..a118eb0f1e672 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -1,8 +1,8 @@ /* * Blackfin On-Chip Real Time Clock Driver - * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] + * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x * - * Copyright 2004-2008 Analog Devices Inc. + * Copyright 2004-2009 Analog Devices Inc. * * Enter bugs at http://blackfin.uclinux.org/ * @@ -363,7 +363,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) struct bfin_rtc *rtc; struct device *dev = &pdev->dev; int ret = 0; - unsigned long timeout; + unsigned long timeout = jiffies + HZ; dev_dbg_stamp(dev); @@ -374,32 +374,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); device_init_wakeup(dev, 1); + /* Register our RTC with the RTC framework */ + rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, + THIS_MODULE); + if (unlikely(IS_ERR(rtc->rtc_dev))) { + ret = PTR_ERR(rtc->rtc_dev); + goto err; + } + /* Grab the IRQ and init the hardware */ ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) - goto err; + goto err_reg; /* sometimes the bootloader touched things, but the write complete was not * enabled, so let's just do a quick timeout here since the IRQ will not fire ... */ - timeout = jiffies + HZ; while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) if (time_after(jiffies, timeout)) break; bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); bfin_write_RTC_SWCNT(0); - /* Register our RTC with the RTC framework */ - rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); - if (unlikely(IS_ERR(rtc->rtc_dev))) { - ret = PTR_ERR(rtc->rtc_dev); - goto err_irq; - } - return 0; - err_irq: - free_irq(IRQ_RTC, dev); - err: +err_reg: + rtc_device_unregister(rtc->rtc_dev); +err: kfree(rtc); return ret; } -- GitLab From 8516a500029890a72622d245f8ed32c4e30969b7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Tue, 30 Jun 2009 11:41:44 -0700 Subject: [PATCH 0456/1002] floppy: fix lock imbalance A crappy macro prevents us unlocking on a fail path. Expand the macro and unlock appropriatelly. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/block/floppy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 862b40c90181b..91b753013780f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3327,7 +3327,10 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, if (!capable(CAP_SYS_ADMIN)) return -EPERM; mutex_lock(&open_lock); - LOCK_FDC(drive, 1); + if (lock_fdc(drive, 1)) { + mutex_unlock(&open_lock); + return -EINTR; + } floppy_type[type] = *g; floppy_type[type].name = "user format"; for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) -- GitLab From 752fa51e4c5182c3c257f1cede90577a7e213c58 Mon Sep 17 00:00:00 2001 From: Wolfgang Illmeyer <wolfgang@illmeyer.com> Date: Tue, 30 Jun 2009 11:41:44 -0700 Subject: [PATCH 0457/1002] hostfs: set maximum filesize in superblock for proper LFS support Maximum file size for hostfs mounts defaults to 2GB, so bigger files cannot be read/written through hostfs. This patch initializes the maximum file size to MAX_LFS_SIZE. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13531 Signed-off-by: Wolfgang Illmeyer <wolfgang@illmeyer.com> Cc: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/hostfs/hostfs_kern.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index fe02ad4740e76..032604e5ef2ca 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -972,6 +972,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) sb->s_blocksize_bits = 10; sb->s_magic = HOSTFS_SUPER_MAGIC; sb->s_op = &hostfs_sbops; + sb->s_maxbytes = MAX_LFS_FILESIZE; /* NULL is printed as <NULL> by sprintf: avoid that. */ if (req_root == NULL) -- GitLab From aee3ff1b413cff44e7d91dd1901cacd8988ce9cf Mon Sep 17 00:00:00 2001 From: David Howells <dhowells@redhat.com> Date: Tue, 30 Jun 2009 22:24:54 +0100 Subject: [PATCH 0458/1002] FRV: Wire up new syscalls Wire up new syscalls rt_tgsigqueueinfo and perf_counter_open. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/frv/include/asm/unistd.h | 4 +++- arch/frv/kernel/entry.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index 96d78d5d2c419..4a8fb427ce0a2 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h @@ -341,10 +341,12 @@ #define __NR_inotify_init1 332 #define __NR_preadv 333 #define __NR_pwritev 334 +#define __NR_rt_tgsigqueueinfo 335 +#define __NR_perf_counter_open 336 #ifdef __KERNEL__ -#define NR_syscalls 335 +#define NR_syscalls 337 #define __ARCH_WANT_IPC_PARSE_VERSION /* #define __ARCH_WANT_OLD_READDIR */ diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 356e0e327a892..fde1e446b440e 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1524,5 +1524,7 @@ sys_call_table: .long sys_inotify_init1 .long sys_preadv .long sys_pwritev + .long sys_rt_tgsigqueueinfo /* 335 */ + .long sys_perf_counter_open syscall_table_size = (. - sys_call_table) -- GitLab From 6086071005674eb982d898c75269c931240154cf Mon Sep 17 00:00:00 2001 From: David Howells <dhowells@redhat.com> Date: Tue, 30 Jun 2009 22:33:15 +0100 Subject: [PATCH 0459/1002] MN10300: Wire up new syscalls Wire up new syscalls rt_tgsigqueueinfo and perf_counter_open. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/mn10300/include/asm/unistd.h | 4 +++- arch/mn10300/kernel/entry.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h index fef5b434dadcc..fad68616af32b 100644 --- a/arch/mn10300/include/asm/unistd.h +++ b/arch/mn10300/include/asm/unistd.h @@ -346,10 +346,12 @@ #define __NR_inotify_init1 333 #define __NR_preadv 334 #define __NR_pwritev 335 +#define __NR_rt_tgsigqueueinfo 336 +#define __NR_perf_counter_open 337 #ifdef __KERNEL__ -#define NR_syscalls 326 +#define NR_syscalls 338 /* * specify the deprecated syscalls we want to support on this arch diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 7408a27199f34..e0d2563af4f24 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -722,6 +722,8 @@ ENTRY(sys_call_table) .long sys_inotify_init1 .long sys_preadv .long sys_pwritev /* 335 */ + .long sys_rt_tgsigqueueinfo + .long sys_perf_counter_open nr_syscalls=(.-sys_call_table)/4 -- GitLab From 1ec22eb2b4a2e1a763106bce36b11c02eaa84e61 Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Wed, 1 Jul 2009 12:27:21 +1000 Subject: [PATCH 0460/1002] md: fix error path when duplicate name is found on md device creation. When an md device is created by name (rather than number) we need to check that the name is not already in use. If this check finds a duplicate, we return an error without dropping the lock or freeing the newly create mddev. This patch fixes that. Cc: stable@kernel.org Found-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 2166af8a76546..58bee2366ea8e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3862,6 +3862,8 @@ static int md_alloc(dev_t dev, char *name) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); + mutex_unlock(&disks_mutex); + mddev_put(mddev); return -EEXIST; } spin_unlock(&all_mddevs_lock); -- GitLab From 0909dc448c98ed5021c87ffdfc09fb473aa464ab Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Wed, 1 Jul 2009 12:27:21 +1000 Subject: [PATCH 0461/1002] md: tidy up error paths in md_alloc As the recent bug in md_alloc showed, having a single exit path for unlocking and putting is a good idea. So restructure md_alloc to have a single mutex_unlock and mddev_put, and use gotos where necessary. Found-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/md.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 58bee2366ea8e..65fe35b5e34a2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3846,11 +3846,9 @@ static int md_alloc(dev_t dev, char *name) flush_scheduled_work(); mutex_lock(&disks_mutex); - if (mddev->gendisk) { - mutex_unlock(&disks_mutex); - mddev_put(mddev); - return -EEXIST; - } + error = -EEXIST; + if (mddev->gendisk) + goto abort; if (name) { /* Need to ensure that 'name' is not a duplicate. @@ -3862,19 +3860,15 @@ static int md_alloc(dev_t dev, char *name) if (mddev2->gendisk && strcmp(mddev2->gendisk->disk_name, name) == 0) { spin_unlock(&all_mddevs_lock); - mutex_unlock(&disks_mutex); - mddev_put(mddev); - return -EEXIST; + goto abort; } spin_unlock(&all_mddevs_lock); } + error = -ENOMEM; mddev->queue = blk_alloc_queue(GFP_KERNEL); - if (!mddev->queue) { - mutex_unlock(&disks_mutex); - mddev_put(mddev); - return -ENOMEM; - } + if (!mddev->queue) + goto abort; mddev->queue->queuedata = mddev; /* Can be unlocked because the queue is new: no concurrency */ @@ -3884,11 +3878,9 @@ static int md_alloc(dev_t dev, char *name) disk = alloc_disk(1 << shift); if (!disk) { - mutex_unlock(&disks_mutex); blk_cleanup_queue(mddev->queue); mddev->queue = NULL; - mddev_put(mddev); - return -ENOMEM; + goto abort; } disk->major = MAJOR(mddev->unit); disk->first_minor = unit << shift; @@ -3910,16 +3902,22 @@ static int md_alloc(dev_t dev, char *name) mddev->gendisk = disk; error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk_to_dev(disk)->kobj, "%s", "md"); - mutex_unlock(&disks_mutex); - if (error) + if (error) { + /* This isn't possible, but as kobject_init_and_add is marked + * __must_check, we must do something with the result + */ printk(KERN_WARNING "md: cannot register %s/md - name in use\n", disk->disk_name); - else { + error = 0; + } + abort: + mutex_unlock(&disks_mutex); + if (!error) { kobject_uevent(&mddev->kobj, KOBJ_ADD); mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); } mddev_put(mddev); - return 0; + return error; } static struct kobject *md_probe(dev_t dev, int *part, void *data) -- GitLab From eaea43abf30c8ccb447c190e7c94b46b5f75eae6 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:49:40 +0000 Subject: [PATCH 0462/1002] cdc_eem: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/cdc_eem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 80e01778dd3ba..cd35d50e46d46 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -319,7 +319,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return crc == crc2; if (unlikely(crc != crc2)) { - dev->stats.rx_errors++; + dev->net->stats.rx_errors++; dev_kfree_skb_any(skb2); } else usbnet_skb_return(dev, skb2); -- GitLab From 9612101cb33862cc160069cc8423926d61db51f8 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:50:51 +0000 Subject: [PATCH 0463/1002] dm9601: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/dm9601.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 7ae82446b93ae..1d3730d6690fc 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -513,11 +513,11 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) len = (skb->data[1] | (skb->data[2] << 8)) - 4; if (unlikely(status & 0xbf)) { - if (status & 0x01) dev->stats.rx_fifo_errors++; - if (status & 0x02) dev->stats.rx_crc_errors++; - if (status & 0x04) dev->stats.rx_frame_errors++; - if (status & 0x20) dev->stats.rx_missed_errors++; - if (status & 0x90) dev->stats.rx_length_errors++; + if (status & 0x01) dev->net->stats.rx_fifo_errors++; + if (status & 0x02) dev->net->stats.rx_crc_errors++; + if (status & 0x04) dev->net->stats.rx_frame_errors++; + if (status & 0x20) dev->net->stats.rx_missed_errors++; + if (status & 0x90) dev->net->stats.rx_length_errors++; return 0; } -- GitLab From a22d2b36a2c4ca58c5914072a88704377bbd34f8 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:51:40 +0000 Subject: [PATCH 0464/1002] net1080: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/net1080.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 034e8a73ca6b4..aeb1ab03a9ee6 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -433,7 +433,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) dbg("rx framesize %d range %d..%d mtu %d", skb->len, net->hard_header_len, dev->hard_mtu, net->mtu); #endif - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; nc_ensure_sync(dev); return 0; } @@ -442,12 +442,12 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) hdr_len = le16_to_cpup(&header->hdr_len); packet_len = le16_to_cpup(&header->packet_len); if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) { - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; dbg("packet too big, %d", packet_len); nc_ensure_sync(dev); return 0; } else if (hdr_len < MIN_HEADER) { - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; dbg("header too short, %d", hdr_len); nc_ensure_sync(dev); return 0; @@ -465,21 +465,21 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if ((packet_len & 0x01) == 0) { if (skb->data [packet_len] != PAD_BYTE) { - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; dbg("bad pad"); return 0; } skb_trim(skb, skb->len - 1); } if (skb->len != packet_len) { - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; dbg("bad packet len %d (expected %d)", skb->len, packet_len); nc_ensure_sync(dev); return 0; } if (header->packet_id != get_unaligned(&trailer->packet_id)) { - dev->stats.rx_fifo_errors++; + dev->net->stats.rx_fifo_errors++; dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", le16_to_cpu(header->packet_id), le16_to_cpu(trailer->packet_id)); -- GitLab From 58e2e7d5913e7a2a6d87ef30d3b52e66b88e6e1d Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:52:26 +0000 Subject: [PATCH 0465/1002] rndis_host: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/rndis_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 1bf243ef950e2..2232232b79899 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -487,7 +487,7 @@ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET || skb->len < msg_len || (data_offset + data_len + 8) > msg_len)) { - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d", le32_to_cpu(hdr->msg_type), msg_len, data_offset, data_len, skb->len); -- GitLab From 80667ac13a6cf2c3a3ff275a2a72809671299acb Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:53:00 +0000 Subject: [PATCH 0466/1002] smsc95xx: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/smsc95xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 89a91f8c22dea..fe045896406bd 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1108,18 +1108,18 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (unlikely(header & RX_STS_ES_)) { if (netif_msg_rx_err(dev)) devdbg(dev, "Error header=0x%08x", header); - dev->stats.rx_errors++; - dev->stats.rx_dropped++; + dev->net->stats.rx_errors++; + dev->net->stats.rx_dropped++; if (header & RX_STS_CRC_) { - dev->stats.rx_crc_errors++; + dev->net->stats.rx_crc_errors++; } else { if (header & (RX_STS_TL_ | RX_STS_RF_)) - dev->stats.rx_frame_errors++; + dev->net->stats.rx_frame_errors++; if ((header & RX_STS_LE_) && (!(header & RX_STS_FT_))) - dev->stats.rx_length_errors++; + dev->net->stats.rx_length_errors++; } } else { /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ -- GitLab From 7963837f933df8a8ada56fa8f8205ebab40f84d0 Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:53:28 +0000 Subject: [PATCH 0467/1002] usbnet: Use netdev stats structure Now that netdev has its own stats structure we should use that instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/usb/usbnet.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 22c0585a03198..edfd9e10ceba2 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -234,8 +234,8 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) int status; skb->protocol = eth_type_trans (skb, dev->net); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += skb->len; if (netif_msg_rx_status (dev)) devdbg (dev, "< rx, len %zu, type 0x%x", @@ -397,7 +397,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) if (netif_msg_rx_err (dev)) devdbg (dev, "drop"); error: - dev->stats.rx_errors++; + dev->net->stats.rx_errors++; skb_queue_tail (&dev->done, skb); } } @@ -420,8 +420,8 @@ static void rx_complete (struct urb *urb) case 0: if (skb->len < dev->net->hard_header_len) { entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; if (netif_msg_rx_err (dev)) devdbg (dev, "rx length %d", skb->len); } @@ -433,7 +433,7 @@ static void rx_complete (struct urb *urb) * storm, recovering as needed. */ case -EPIPE: - dev->stats.rx_errors++; + dev->net->stats.rx_errors++; usbnet_defer_kevent (dev, EVENT_RX_HALT); // FALLTHROUGH @@ -451,7 +451,7 @@ static void rx_complete (struct urb *urb) case -EPROTO: case -ETIME: case -EILSEQ: - dev->stats.rx_errors++; + dev->net->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); if (netif_msg_link (dev)) @@ -465,12 +465,12 @@ static void rx_complete (struct urb *urb) /* data overrun ... flush fifo? */ case -EOVERFLOW: - dev->stats.rx_over_errors++; + dev->net->stats.rx_over_errors++; // FALLTHROUGH default: entry->state = rx_cleanup; - dev->stats.rx_errors++; + dev->net->stats.rx_errors++; if (netif_msg_rx_err (dev)) devdbg (dev, "rx status %d", urb_status); break; @@ -583,8 +583,8 @@ int usbnet_stop (struct net_device *net) if (netif_msg_ifdown (dev)) devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", - dev->stats.rx_packets, dev->stats.tx_packets, - dev->stats.rx_errors, dev->stats.tx_errors + net->stats.rx_packets, net->stats.tx_packets, + net->stats.rx_errors, net->stats.tx_errors ); // ensure there are no more active urbs @@ -891,10 +891,10 @@ static void tx_complete (struct urb *urb) struct usbnet *dev = entry->dev; if (urb->status == 0) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += entry->length; + dev->net->stats.tx_packets++; + dev->net->stats.tx_bytes += entry->length; } else { - dev->stats.tx_errors++; + dev->net->stats.tx_errors++; switch (urb->status) { case -EPIPE: @@ -1020,7 +1020,7 @@ int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) devdbg (dev, "drop, code %d", retval); drop: retval = NET_XMIT_SUCCESS; - dev->stats.tx_dropped++; + dev->net->stats.tx_dropped++; if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb); -- GitLab From d9d62f3f2c6fa609883714f6fd6cd710a83d307f Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Mon, 29 Jun 2009 16:54:12 +0000 Subject: [PATCH 0468/1002] usbnet: Remove private stats structure Now that nothing uses the private stats structure we can remove it. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- include/linux/usb/usbnet.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 5d44059f6d63f..310e18a880fff 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -42,7 +42,6 @@ struct usbnet { /* protocol/interface state */ struct net_device *net; - struct net_device_stats stats; int msg_enable; unsigned long data [5]; u32 xid; -- GitLab From 88d2b81f4ee8f9ea3798dbe6105beb5609844317 Mon Sep 17 00:00:00 2001 From: Don Skidmore <donald.c.skidmore@intel.com> Date: Tue, 30 Jun 2009 11:43:55 +0000 Subject: [PATCH 0469/1002] ixgbe: Fix SFP log messages We had a wide range of log messages for the same sort of SFP failure. This patch makes them all more similar and less confusing along with converting them to dev_err. Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e756e220db326..30d8c0e41a9d5 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2701,7 +2701,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) */ err = hw->phy.ops.identify(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err); + dev_err(&adapter->pdev->dev, "failed to initialize because " + "an unsupported SFP+ module type was detected.\n" + "Reload the driver after installing a supported " + "module.\n"); ixgbe_down(adapter); return err; } @@ -3720,10 +3723,11 @@ static void ixgbe_sfp_task(struct work_struct *work) goto reschedule; ret = hw->phy.ops.reset(hw); if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { - DPRINTK(PROBE, ERR, "failed to initialize because an " - "unsupported SFP+ module type was detected.\n" - "Reload the driver after installing a " - "supported module.\n"); + dev_err(&adapter->pdev->dev, "failed to initialize " + "because an unsupported SFP+ module type " + "was detected.\n" + "Reload the driver after installing a " + "supported module.\n"); unregister_netdev(adapter->netdev); } else { DPRINTK(PROBE, INFO, "detected SFP+: %d\n", @@ -4526,7 +4530,10 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; err = hw->phy.ops.identify_sfp(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err); + dev_err(&adapter->pdev->dev, "failed to initialize because " + "an unsupported SFP+ module type was detected.\n" + "Reload the driver after installing a supported " + "module.\n"); ixgbe_down(adapter); return; } @@ -5513,8 +5520,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, round_jiffies(jiffies + (2 * HZ))); err = 0; } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to load because an " - "unsupported SFP+ module type was detected.\n"); + dev_err(&adapter->pdev->dev, "failed to initialize because " + "an unsupported SFP+ module type was detected.\n" + "Reload the driver after installing a supported " + "module.\n"); goto err_sw_init; } else if (err) { dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err); -- GitLab From a380137900fca5c79e6daa9500bdb6ea5649188e Mon Sep 17 00:00:00 2001 From: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Date: Tue, 30 Jun 2009 11:44:16 +0000 Subject: [PATCH 0470/1002] ixgbe: Fix device capabilities of 82599 single speed fiber NICs. 82599 single speed fiber modules only support 10G/Full. Return proper device capabilities while querrying the adapter and error while changing device advertisement/speed/duplex capabilities. Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_ethtool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 86f4f3e36f27f..0f7b6a3a2e682 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -139,7 +139,7 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->autoneg = AUTONEG_ENABLE; ecmd->transceiver = XCVR_EXTERNAL; if ((hw->phy.media_type == ixgbe_media_type_copper) || - (hw->mac.type == ixgbe_mac_82599EB)) { + (hw->phy.multispeed_fiber)) { ecmd->supported |= (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg); @@ -217,7 +217,7 @@ static int ixgbe_set_settings(struct net_device *netdev, s32 err = 0; if ((hw->phy.media_type == ixgbe_media_type_copper) || - (hw->mac.type == ixgbe_mac_82599EB)) { + (hw->phy.multispeed_fiber)) { /* 10000/copper and 1000/copper must autoneg * this function does not support any duplex forcing, but can * limit the advertising of the adapter to only 10000 or 1000 */ @@ -245,6 +245,7 @@ static int ixgbe_set_settings(struct net_device *netdev, } else { /* in this case we currently only support 10Gb/FULL */ if ((ecmd->autoneg == AUTONEG_ENABLE) || + (ecmd->advertising != ADVERTISED_10000baseT_Full) || (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) return -EINVAL; } -- GitLab From a1f25324b93ecdab1cbb27d3e9c4cafecb06ceda Mon Sep 17 00:00:00 2001 From: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Date: Tue, 30 Jun 2009 11:44:36 +0000 Subject: [PATCH 0471/1002] ixgbe: Fix link capabilities during adapter resets Adapter link advertisement capabilities were not persistent during adapter resets. While configuring multispeed fiber link check for phy autoneg_advertised settings before overwriting with default link capabilities Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 30d8c0e41a9d5..fce2ef49b3a73 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4506,7 +4506,8 @@ static void ixgbe_multispeed_fiber_task(struct work_struct *work) u32 autoneg; adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK; - if (hw->mac.ops.get_link_capabilities) + autoneg = hw->phy.autoneg_advertised; + if ((!autoneg) && (hw->mac.ops.get_link_capabilities)) hw->mac.ops.get_link_capabilities(hw, &autoneg, &hw->mac.autoneg); if (hw->mac.ops.setup_link_speed) -- GitLab From 4f57ca6e17edfc56ddde5c87eb893e47e0d2d343 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg <jesse.brandeburg@intel.com> Date: Tue, 30 Jun 2009 11:44:56 +0000 Subject: [PATCH 0472/1002] ixgbe: fix unmap length bug This patch addresses three WARN_ON statements from DMA-API debug code ixgbe is mapping more than it unmaps, reduce the length of the map call and remove the "used once" local variable. found by Joerg Roedel <joerg.roedel@amd.com> in 2.6.30, so is a candidate for -stable. in addition, fix missing ->dma = 0 after unmap to prevent double free with pci_unmap_single and lastly, don't unmap (half) pages that aren't mapped. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> CC: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index fce2ef49b3a73..5588ef493a3d9 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -563,7 +563,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *bi; unsigned int i; - unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN; i = rx_ring->next_to_use; bi = &rx_ring->rx_buffer_info[i]; @@ -593,7 +592,9 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, if (!bi->skb) { struct sk_buff *skb; - skb = netdev_alloc_skb(adapter->netdev, bufsz); + skb = netdev_alloc_skb(adapter->netdev, + (rx_ring->rx_buf_len + + NET_IP_ALIGN)); if (!skb) { adapter->alloc_rx_buff_failed++; @@ -608,7 +609,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, skb_reserve(skb, NET_IP_ALIGN); bi->skb = skb; - bi->dma = pci_map_single(pdev, skb->data, bufsz, + bi->dma = pci_map_single(pdev, skb->data, + rx_ring->rx_buf_len, PCI_DMA_FROMDEVICE); } /* Refresh the desc even if buffer_addrs didn't change because @@ -732,6 +734,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, pci_unmap_single(pdev, rx_buffer_info->dma, rx_ring->rx_buf_len, PCI_DMA_FROMDEVICE); + rx_buffer_info->dma = 0; skb_put(skb, len); } @@ -2815,9 +2818,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, } if (!rx_buffer_info->page) continue; - pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2, - PCI_DMA_FROMDEVICE); - rx_buffer_info->page_dma = 0; + if (rx_buffer_info->page_dma) { + pci_unmap_page(pdev, rx_buffer_info->page_dma, + PAGE_SIZE / 2, PCI_DMA_FROMDEVICE); + rx_buffer_info->page_dma = 0; + } put_page(rx_buffer_info->page); rx_buffer_info->page = NULL; rx_buffer_info->page_offset = 0; -- GitLab From 91615f765a2935b6cbae424b9eee1585ed681ae6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg <jesse.brandeburg@intel.com> Date: Tue, 30 Jun 2009 12:45:15 +0000 Subject: [PATCH 0473/1002] igb: fix unmap length bug driver was mixing NET_IP_ALIGN count bytes in map/unmap calls unevenly. Only map the bytes that the hardware might dma into also fix unmap related bug where ->dma was not being cleared after unmap Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/igb/igb_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ea17319624aa7..468356d124ea7 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4549,11 +4549,12 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, cleaned = true; cleaned_count++; + /* this is the fast path for the non-packet split case */ if (!adapter->rx_ps_hdr_size) { pci_unmap_single(pdev, buffer_info->dma, - adapter->rx_buffer_len + - NET_IP_ALIGN, + adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; skb_put(skb, length); goto send_up; } @@ -4570,8 +4571,9 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, if (!skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, buffer_info->dma, - adapter->rx_ps_hdr_size + NET_IP_ALIGN, + adapter->rx_ps_hdr_size, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; skb_put(skb, hlen); } @@ -4713,7 +4715,6 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, bufsz = adapter->rx_ps_hdr_size; else bufsz = adapter->rx_buffer_len; - bufsz += NET_IP_ALIGN; while (cleaned_count--) { rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); @@ -4737,7 +4738,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, } if (!buffer_info->skb) { - skb = netdev_alloc_skb(netdev, bufsz); + skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN); if (!skb) { adapter->alloc_rx_buff_failed++; goto no_buffers; -- GitLab From 679be3ba0c493eb66d22c206273729ce50925e85 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg <jesse.brandeburg@intel.com> Date: Tue, 30 Jun 2009 12:45:34 +0000 Subject: [PATCH 0474/1002] e1000: fix unmap bug as reported by kerneloops.org [ 121.781161] ------------[ cut here ]------------ [ 121.781171] WARNING: at lib/dma-debug.c:793 check_unmap+0x14e/0x577() [ 121.781173] Hardware name: S5520HC [ 121.781177] e1000 0000:0a:00.0: DMA-API: device driver tries to free DMA memory it has not allocated [device address=0x00000001d688b0fa] [size=1522 bytes] [ 121.781180] Modules linked in: e1000 mdio dca [last unloaded: ixgbe] [ 121.781187] Pid: 4793, comm: bash Tainted: P 2.6.30-master-06161113 #3 [ 121.781190] Call Trace: [ 121.781195] [<ffffffff8123056f>] ? check_unmap+0x14e/0x577 [ 121.781201] [<ffffffff81057a19>] warn_slowpath_common+0x77/0x8f [ 121.781205] [<ffffffff81057ae1>] warn_slowpath_fmt+0x9f/0xa1 [ 121.781212] [<ffffffff81477ce2>] ? _spin_lock_irqsave+0x3f/0x49 [ 121.781216] [<ffffffff8122fa97>] ? get_hash_bucket+0x28/0x33 [ 121.781220] [<ffffffff8123056f>] check_unmap+0x14e/0x577 [ 121.781225] [<ffffffff810e4f48>] ? check_bytes_and_report+0x38/0xcb [ 121.781230] [<ffffffff81230bbf>] debug_dma_unmap_page+0x80/0x92 [ 121.781234] [<ffffffff8122e549>] ? unmap_single+0x1a/0x4e [ 121.781239] [<ffffffff813901e1>] ? __kfree_skb+0x74/0x78 [ 121.781250] [<ffffffffa00662ef>] pci_unmap_single+0x64/0x6d [e1000] [ 121.781259] [<ffffffffa0066344>] e1000_clean_rx_ring+0x4c/0xbf [e1000] [ 121.781268] [<ffffffffa00663df>] e1000_clean_all_rx_rings+0x28/0x36 [e1000] [ 121.781277] [<ffffffffa0067464>] e1000_down+0x138/0x141 [e1000] [ 121.781286] [<ffffffffa00681c2>] __e1000_shutdown+0x6b/0x198 [e1000] [ 121.781296] [<ffffffffa0068405>] e1000_suspend+0x17/0x50 [e1000] [ 121.781301] [<ffffffff81237665>] pci_legacy_suspend+0x3b/0xbe [ 121.781305] [<ffffffff81237bc6>] pci_pm_suspend+0x3e/0xf1 [ 121.781310] [<ffffffff812eaf1c>] pm_op+0x57/0xde [ 121.781314] [<ffffffff812eb444>] dpm_suspend_start+0x31e/0x470 [ 121.781319] [<ffffffff810877da>] suspend_devices_and_enter+0x3e/0x1a2 [ 121.781323] [<ffffffff81087a0f>] enter_state+0xd1/0x127 [ 121.781327] [<ffffffff8108717a>] state_store+0xa7/0xc9 [ 121.781332] [<ffffffff81221843>] kobj_attr_store+0x17/0x19 [ 121.781336] [<ffffffff8113c01e>] sysfs_write_file+0xe5/0x121 [ 121.781341] [<ffffffff810ed165>] vfs_write+0xab/0x105 [ 121.781344] [<ffffffff810ed279>] sys_write+0x47/0x6d [ 121.781349] [<ffffffff81027aab>] system_call_fastpath+0x16/0x1b [ 121.781352] ---[ end trace 97bacaaac2ed7786 ]--- Fix is to correctly zero out internal ->dma value when unmapping and make sure never to unmap unless there specifically was a mapping done. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000/e1000_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e3356f8eb5af..972e06d984c81 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2185,12 +2185,16 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { buffer_info = &rx_ring->buffer_info[i]; - if (buffer_info->skb) { + if (buffer_info->dma) { pci_unmap_single(pdev, buffer_info->dma, buffer_info->length, PCI_DMA_FROMDEVICE); + } + buffer_info->dma = 0; + + if (buffer_info->skb) { dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; } @@ -4033,6 +4037,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, buffer_info->dma, buffer_info->length, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; length = le16_to_cpu(rx_desc->length); /* !EOP means multiple descriptors were used to store a single @@ -4222,6 +4227,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, pci_unmap_single(pdev, buffer_info->dma, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; break; /* while !buffer_info->skb */ } -- GitLab From eab633021c26025b34f36f79f0311d3d99f40ceb Mon Sep 17 00:00:00 2001 From: Andre Detsch <adetsch@br.ibm.com> Date: Tue, 30 Jun 2009 12:46:13 +0000 Subject: [PATCH 0475/1002] e1000: return PCI_ERS_RESULT_DISCONNECT on permanent error PCI drivers that implement the io_error_detected callback should return PCI_ERS_RESULT_DISCONNECT if the state passed in is pci_channel_io_perm_failure. This state is not checked in many of the network drivers. The patch fixes the omission in the e1000 driver. Based on Mike Mason's similar patch for e1000e. Signed-off-by: Andre Detsch <adetsch@br.ibm.com> CC: Mike Mason <mmlnx@us.ibm.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000/e1000_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 972e06d984c81..5b8cbdb4b5201 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4823,6 +4823,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, netif_device_detach(netdev); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (netif_running(netdev)) e1000_down(adapter); pci_disable_device(pdev); -- GitLab From c93b5a76d58656158d195a7df507ebc660010969 Mon Sep 17 00:00:00 2001 From: Mike Mason <mmlnx@us.ibm.com> Date: Tue, 30 Jun 2009 12:45:53 +0000 Subject: [PATCH 0476/1002] e1000e: io_error_detected callback should return PCI_ERS_RESULT_DISCONNECT on permanent failure PCI drivers that implement the io_error_detected callback should return PCI_ERS_RESULT_DISCONNECT if the state passed in is pci_channel_io_perm_failure. This state is not checked in many of the network drivers. This patch fixes the omission in the e1000e driver. Signed-off-by: Mike Mason <mmlnx@us.ibm.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/netdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 679885a122b4d..63415bb6f48ff 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4785,6 +4785,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, netif_device_detach(netdev); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (netif_running(netdev)) e1000e_down(adapter); pci_disable_device(pdev); -- GitLab From 59ed6eecff4aa00c5c5d18ffd180acac108d596e Mon Sep 17 00:00:00 2001 From: Alexander Duyck <alexander.h.duyck@intel.com> Date: Tue, 30 Jun 2009 12:46:34 +0000 Subject: [PATCH 0477/1002] igb: return PCI_ERS_RESULT_DISCONNECT on permanent error PCI drivers that implement the io_error_detected callback should return PCI_ERS_RESULT_DISCONNECT if the state passed in is pci_channel_io_perm_failure. This patch fixes the issue for igb. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 468356d124ea7..be480292aba18 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5339,6 +5339,9 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, netif_device_detach(netdev); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (netif_running(netdev)) igb_down(adapter); pci_disable_device(pdev); -- GitLab From f8a68e752bc4e39644843403168137663c984524 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" <ebiederm@xmission.com> Date: Tue, 30 Jun 2009 16:27:17 +0000 Subject: [PATCH 0478/1002] Revert "ipv4: arp announce, arp_proxy and windows ip conflict verification" This reverts commit 73ce7b01b4496a5fbf9caf63033c874be692333f. After discovering that we don't listen to gratuitious arps in 2.6.30 I tracked the failure down to this commit. The patch makes absolutely no sense. RFC2131 RFC3927 and RFC5227. are all in agreement that an arp request with sip == 0 should be used for the probe (to prevent learning) and an arp request with sip == tip should be used for the gratitous announcement that people can learn from. It appears the author of the broken patch got those two cases confused and modified the code to drop all gratuitous arp traffic. Ouch! Cc: stable@kernel.org Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/arp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8a3881e28aca4..c29d75d8f1b12 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -801,11 +801,8 @@ static int arp_process(struct sk_buff *skb) * cache. */ - /* - * Special case: IPv4 duplicate address detection packet (RFC2131) - * and Gratuitous ARP/ARP Announce. (RFC3927, Section 2.4) - */ - if (sip == 0 || tip == sip) { + /* Special case: IPv4 duplicate address detection packet (RFC2131) */ + if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(net, tip) == RTN_LOCAL && !arp_ignore(in_dev, sip, tip)) -- GitLab From a5c308d4d1659b1f4833b863394e3e24cdbdfc6e Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Wed, 1 Jul 2009 13:15:35 +1000 Subject: [PATCH 0479/1002] md/raid5: suspend shouldn't affect read requests. md allows write to regions on an array to be suspended temporarily. This allows user-space to participate is aspects of reshape. In particular, data can be copied with not risk of a race. We should not be blocking read requests though, so don't. Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/raid5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 92ef9b6abfc7a..1f444ae07f89e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3702,7 +3702,8 @@ static int make_request(struct request_queue *q, struct bio * bi) /* FIXME what if we get a false positive because these * are being updated. */ - if (logical_sector >= mddev->suspend_lo && + if (bio_data_dir(bi) == WRITE && + logical_sector >= mddev->suspend_lo && logical_sector < mddev->suspend_hi) { release_stripe(sh); schedule(); -- GitLab From e62e58a5ffdc98ac28d8dbd070c857620d541f99 Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Wed, 1 Jul 2009 13:15:35 +1000 Subject: [PATCH 0480/1002] md: use interruptible wait when duration is controlled by userspace. User space can set various limits on an md array so that resync waits when it gets to a certain point, or so that I/O is blocked for a short while. When md is waiting against one of these limit, it should use an interruptible wait so as not to add to the load average, and so are not to trigger a warning if the wait goes on for too long. Signed-off-by: NeilBrown <neilb@suse.de> --- drivers/md/md.c | 14 ++++++++++---- drivers/md/raid5.c | 15 +++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 65fe35b5e34a2..0f4a70c43ffcb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6336,10 +6336,16 @@ void md_do_sync(mddev_t *mddev) sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } - if (j >= mddev->resync_max) - wait_event(mddev->recovery_wait, - mddev->resync_max > j - || kthread_should_stop()); + while (j >= mddev->resync_max && !kthread_should_stop()) { + /* As this condition is controlled by user-space, + * we can block indefinitely, so use '_interruptible' + * to avoid triggering warnings. + */ + flush_signals(current); /* just in case */ + wait_event_interruptible(mddev->recovery_wait, + mddev->resync_max > j + || kthread_should_stop()); + } if (kthread_should_stop()) goto interrupted; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 1f444ae07f89e..37835538b58ef 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3699,14 +3699,21 @@ static int make_request(struct request_queue *q, struct bio * bi) goto retry; } } - /* FIXME what if we get a false positive because these - * are being updated. - */ + if (bio_data_dir(bi) == WRITE && logical_sector >= mddev->suspend_lo && logical_sector < mddev->suspend_hi) { release_stripe(sh); - schedule(); + /* As the suspend_* range is controlled by + * userspace, we want an interruptible + * wait. + */ + flush_signals(current); + prepare_to_wait(&conf->wait_for_overlap, + &w, TASK_INTERRUPTIBLE); + if (logical_sector >= mddev->suspend_lo && + logical_sector < mddev->suspend_hi) + schedule(); goto retry; } -- GitLab From 84f7597c116f811cfcb762e645fa258b7e585155 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@igel.co.jp> Date: Wed, 1 Jul 2009 04:55:35 +0000 Subject: [PATCH 0481/1002] sh: fix se7724 ceu names Use "ceu0" and "ceu1" as CEU names instead of "ceu". This fixes "memchunk" kernel command line selection on the solution engine 7724 board. With this patch applied use "memchunk.ceu0=1m" or "memchunk.ceu1=1m" on kernel command line to override physically memory size to one meg for CEU0 or CEU1. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/boards/mach-se/7724/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 21d18005fb4ad..c050a8d76dfd1 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -454,7 +454,7 @@ static int __init devices_setup(void) gpio_request(GPIO_FN_VIO0_CLK, NULL); gpio_request(GPIO_FN_VIO0_FLD, NULL); gpio_request(GPIO_FN_VIO0_HD, NULL); - platform_resource_setup_memory(&ceu0_device, "ceu", 4 << 20); + platform_resource_setup_memory(&ceu0_device, "ceu0", 4 << 20); /* enable CEU1 */ gpio_request(GPIO_FN_VIO1_D7, NULL); @@ -469,7 +469,7 @@ static int __init devices_setup(void) gpio_request(GPIO_FN_VIO1_HD, NULL); gpio_request(GPIO_FN_VIO1_VD, NULL); gpio_request(GPIO_FN_VIO1_CLK, NULL); - platform_resource_setup_memory(&ceu1_device, "ceu", 4 << 20); + platform_resource_setup_memory(&ceu1_device, "ceu1", 4 << 20); /* KEYSC */ gpio_request(GPIO_FN_KEYOUT5_IN5, NULL); -- GitLab From 0802d9e55cc6be6bd1b13f9dc9ef5aa6d24bca77 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@igel.co.jp> Date: Wed, 1 Jul 2009 05:16:31 +0000 Subject: [PATCH 0482/1002] sh: re-add LCDC fbdev support to the Migo-R defconfig Re-add LCDC fbdev support to the Migo-R defconfig. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/configs/migor_defconfig | 53 +++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index da627d22c009c..b18cfd39cac60 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig @@ -309,7 +309,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00001000 CONFIG_BOOT_LINK_OFFSET=0x00800000 CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp" +CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp" # # Bus options @@ -858,7 +858,35 @@ CONFIG_VIDEO_SH_MOBILE_CEU=y # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_SH_MOBILE_LCDC=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -870,6 +898,27 @@ CONFIG_VIDEO_SH_MOBILE_CEU=y # Console display driver support # CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +CONFIG_FONT_MINI_4x6=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +# CONFIG_LOGO_SUPERH_MONO is not set +CONFIG_LOGO_SUPERH_VGA16=y +# CONFIG_LOGO_SUPERH_CLUT224 is not set # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y -- GitLab From 1e1689536f346a431b748dc8ad9ac0828d2c065d Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 1 Jul 2009 08:34:32 +0200 Subject: [PATCH 0483/1002] ALSA: hda - Add missing static to patch_ca0110() Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_ca0110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index 392d108c35587..019ca7cb56d7d 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c @@ -510,7 +510,7 @@ static int ca0110_parse_auto_config(struct hda_codec *codec) } -int patch_ca0110(struct hda_codec *codec) +static int patch_ca0110(struct hda_codec *codec) { struct ca0110_spec *spec; int err; -- GitLab From 9198aa77b69647d1d91207f8075763abe7dc0bf4 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Wed, 1 Jul 2009 05:35:13 +0200 Subject: [PATCH 0484/1002] perf_counter tools: Fix storage size allocation of callchain list Fix a confusion while giving the size of a callchain list during its allocation. We are using the wrong structure size. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246419315-9968-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/callchain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index ad3c285789611..bbf7813fefe03 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -74,7 +74,7 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) for (i = start; i < chain->nr; i++) { struct callchain_list *call; - call = malloc(sizeof(*chain)); + call = malloc(sizeof(*call)); if (!call) { perror("not enough memory for the code path tree"); return; -- GitLab From 4424961ad6621a02c6b4c9093e801002c1bb9f65 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Wed, 1 Jul 2009 05:35:14 +0200 Subject: [PATCH 0485/1002] perf_counter tools: Resolve symbols in callchains This patch resolves the names, when possible, of each ip present in the callchains while using the -c option with perf report. Example: 5.40% [k] __d_lookup 5.37% perf_callchain perf_counter_overflow intel_pmu_handle_irq perf_counter_nmi_handler notifier_call_chain atomic_notifier_call_chain notify_die do_nmi nmi do_lookup __link_path_walk path_walk do_path_lookup user_path_at sys_faccessat sys_access system_call_fastpath 0x7fb609846f77 0.01% perf_callchain perf_counter_overflow intel_pmu_handle_irq perf_counter_nmi_handler notifier_call_chain atomic_notifier_call_chain notify_die do_nmi nmi do_lookup __link_path_walk path_walk do_path_lookup user_path_at sys_faccessat Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246419315-9968-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 102 +++++++++++++++++++++++------------- tools/perf/util/callchain.c | 33 +++++++----- tools/perf/util/callchain.h | 5 +- 3 files changed, 90 insertions(+), 50 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3f5d8ea05ff09..197793051fa51 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -794,8 +794,15 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) ret += callchain__fprintf(fp, self->parent, total_samples); - list_for_each_entry(chain, &self->val, list) - ret += fprintf(fp, " %p\n", (void *)chain->ip); + list_for_each_entry(chain, &self->val, list) { + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + if (chain->sym) + ret += fprintf(fp, " %s\n", chain->sym->name); + else + ret += fprintf(fp, " %p\n", + (void *)chain->ip); + } return ret; } @@ -930,6 +937,55 @@ static int call__match(struct symbol *sym) return 0; } +static struct symbol ** +resolve_callchain(struct thread *thread, struct map *map, + struct ip_callchain *chain, struct hist_entry *entry) +{ + int i; + struct symbol **syms; + u64 context = PERF_CONTEXT_MAX; + + if (callchain) { + syms = calloc(chain->nr, sizeof(*syms)); + if (!syms) { + fprintf(stderr, "Can't allocate memory for symbols\n"); + exit(-1); + } + } + + for (i = 0; i < chain->nr; i++) { + u64 ip = chain->ips[i]; + struct dso *dso = NULL; + struct symbol *sym; + + if (ip >= PERF_CONTEXT_MAX) { + context = ip; + continue; + } + + switch (context) { + case PERF_CONTEXT_KERNEL: + dso = kernel_dso; + break; + default: + break; + } + + sym = resolve_symbol(thread, NULL, &dso, &ip); + + if (sym) { + if (sort__has_parent && call__match(sym) && + !entry->parent) + entry->parent = sym; + if (!callchain) + break; + syms[i] = sym; + } + } + + return syms; +} + /* * collect histogram counts */ @@ -942,6 +998,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, struct rb_node **p = &hist.rb_node; struct rb_node *parent = NULL; struct hist_entry *he; + struct symbol **syms = NULL; struct hist_entry entry = { .thread = thread, .map = map, @@ -955,39 +1012,11 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, }; int cmp; - if (sort__has_parent && chain) { - u64 context = PERF_CONTEXT_MAX; - int i; - - for (i = 0; i < chain->nr; i++) { - u64 ip = chain->ips[i]; - struct dso *dso = NULL; - struct symbol *sym; - - if (ip >= PERF_CONTEXT_MAX) { - context = ip; - continue; - } - - switch (context) { case PERF_CONTEXT_HV: dso = hypervisor_dso; break; - case PERF_CONTEXT_KERNEL: - dso = kernel_dso; - break; - default: - break; - } - - sym = resolve_symbol(thread, NULL, &dso, &ip); - - if (sym && call__match(sym)) { - entry.parent = sym; - break; - } - } - } + if ((sort__has_parent || callchain) && chain) + syms = resolve_callchain(thread, map, chain, &entry); while (*p != NULL) { parent = *p; @@ -997,8 +1026,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, if (!cmp) { he->count += count; - if (callchain) - append_chain(&he->callchain, chain); + if (callchain) { + append_chain(&he->callchain, chain, syms); + free(syms); + } return 0; } @@ -1014,7 +1045,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, *he = entry; if (callchain) { callchain_init(&he->callchain); - append_chain(&he->callchain, chain); + append_chain(&he->callchain, chain, syms); + free(syms); } rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, &hist); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index bbf7813fefe03..6568cb198ba6f 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -67,7 +67,8 @@ static struct callchain_node *create_child(struct callchain_node *parent) } static void -fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) +fill_node(struct callchain_node *node, struct ip_callchain *chain, int start, + struct symbol **syms) { int i; @@ -80,24 +81,26 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) return; } call->ip = chain->ips[i]; + call->sym = syms[i]; list_add_tail(&call->list, &node->val); } node->val_nr = i - start; } -static void add_child(struct callchain_node *parent, struct ip_callchain *chain) +static void add_child(struct callchain_node *parent, struct ip_callchain *chain, + struct symbol **syms) { struct callchain_node *new; new = create_child(parent); - fill_node(new, chain, parent->val_nr); + fill_node(new, chain, parent->val_nr, syms); new->hit = 1; } static void split_add_child(struct callchain_node *parent, struct ip_callchain *chain, - struct callchain_list *to_split, int idx) + struct callchain_list *to_split, int idx, struct symbol **syms) { struct callchain_node *new; @@ -109,21 +112,22 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, parent->val_nr = idx; /* create the new one */ - add_child(parent, chain); + add_child(parent, chain, syms); } static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start); + int start, struct symbol **syms); static int -__append_chain_children(struct callchain_node *root, struct ip_callchain *chain) +__append_chain_children(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms) { struct callchain_node *rnode; /* lookup in childrens */ list_for_each_entry(rnode, &root->children, brothers) { - int ret = __append_chain(rnode, chain, root->val_nr); + int ret = __append_chain(rnode, chain, root->val_nr, syms); if (!ret) return 0; } @@ -132,7 +136,7 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain) static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start) + int start, struct symbol **syms) { struct callchain_list *cnode; int i = start; @@ -154,7 +158,7 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, /* we match only a part of the node. Split it and add the new chain */ if (i < root->val_nr) { - split_add_child(root, chain, cnode, i); + split_add_child(root, chain, cnode, i, syms); return 0; } @@ -164,11 +168,12 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, return 0; } - return __append_chain_children(root, chain); + return __append_chain_children(root, chain, syms); } -void append_chain(struct callchain_node *root, struct ip_callchain *chain) +void append_chain(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms) { - if (__append_chain_children(root, chain) == -1) - add_child(root, chain); + if (__append_chain_children(root, chain, syms) == -1) + add_child(root, chain, syms); } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index fa1cd2f71fd3b..c942daa712e6f 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -4,6 +4,7 @@ #include "../perf.h" #include "list.h" #include "rbtree.h" +#include "symbol.h" struct callchain_node { @@ -18,6 +19,7 @@ struct callchain_node { struct callchain_list { unsigned long ip; + struct symbol *sym; struct list_head list; }; @@ -28,6 +30,7 @@ static inline void callchain_init(struct callchain_node *node) INIT_LIST_HEAD(&node->val); } -void append_chain(struct callchain_node *root, struct ip_callchain *chain); +void append_chain(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms); void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); #endif -- GitLab From deac911cbdcb124fa0cee47c588e0cb0400b23b7 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Wed, 1 Jul 2009 05:35:15 +0200 Subject: [PATCH 0486/1002] perf_counter tools: Various fixes for callchains The symbol resolving has of course revealed some bugs in the callchain tree handling. This patch fixes some of them, including: - inherit the children from the parents while splitting a node - fix list range moving - fix indexes setting in callchains - create a child on the current node if the path doesn't match in the existent children (was only done on the root) - compare using symbols when possible so that we can match a function using any ip inside by referring to its start address. The practical effects are: - remove double callchains - fix upside down or any random order of callchains - fix wrong paths - fix bad hits and percentage accounts Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246419315-9968-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/callchain.c | 122 ++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 32 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 6568cb198ba6f..440db12c63594 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -4,6 +4,9 @@ * Handle the callchains from the stream in an ad-hoc radix tree and then * sort them in an rbtree. * + * Using a radix for code path provides a fast retrieval and factorizes + * memory use. Also that lets us use the paths in a hierarchical graph view. + * */ #include <stdlib.h> @@ -14,7 +17,8 @@ #include "callchain.h" -static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) +static void +rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; @@ -49,7 +53,12 @@ void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) rb_insert_callchain(rb_root, node); } -static struct callchain_node *create_child(struct callchain_node *parent) +/* + * Create a child for a parent. If inherit_children, then the new child + * will become the new parent of it's parent children + */ +static struct callchain_node * +create_child(struct callchain_node *parent, bool inherit_children) { struct callchain_node *new; @@ -61,14 +70,27 @@ static struct callchain_node *create_child(struct callchain_node *parent) new->parent = parent; INIT_LIST_HEAD(&new->children); INIT_LIST_HEAD(&new->val); + + if (inherit_children) { + struct callchain_node *next; + + list_splice(&parent->children, &new->children); + INIT_LIST_HEAD(&parent->children); + + list_for_each_entry(next, &new->children, brothers) + next->parent = new; + } list_add_tail(&new->brothers, &parent->children); return new; } +/* + * Fill the node with callchain values + */ static void -fill_node(struct callchain_node *node, struct ip_callchain *chain, int start, - struct symbol **syms) +fill_node(struct callchain_node *node, struct ip_callchain *chain, + int start, struct symbol **syms) { int i; @@ -84,54 +106,80 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain, int start, call->sym = syms[i]; list_add_tail(&call->list, &node->val); } - node->val_nr = i - start; + node->val_nr = chain->nr - start; + if (!node->val_nr) + printf("Warning: empty node in callchain tree\n"); } -static void add_child(struct callchain_node *parent, struct ip_callchain *chain, - struct symbol **syms) +static void +add_child(struct callchain_node *parent, struct ip_callchain *chain, + int start, struct symbol **syms) { struct callchain_node *new; - new = create_child(parent); - fill_node(new, chain, parent->val_nr, syms); + new = create_child(parent, false); + fill_node(new, chain, start, syms); new->hit = 1; } +/* + * Split the parent in two parts (a new child is created) and + * give a part of its callchain to the created child. + * Then create another child to host the given callchain of new branch + */ static void split_add_child(struct callchain_node *parent, struct ip_callchain *chain, - struct callchain_list *to_split, int idx, struct symbol **syms) + struct callchain_list *to_split, int idx_parents, int idx_local, + struct symbol **syms) { struct callchain_node *new; + struct list_head *old_tail; + int idx_total = idx_parents + idx_local; /* split */ - new = create_child(parent); - list_move_tail(&to_split->list, &new->val); - new->hit = parent->hit; - parent->hit = 0; - parent->val_nr = idx; + new = create_child(parent, true); + + /* split the callchain and move a part to the new child */ + old_tail = parent->val.prev; + list_del_range(&to_split->list, old_tail); + new->val.next = &to_split->list; + new->val.prev = old_tail; + to_split->list.prev = &new->val; + old_tail->next = &new->val; - /* create the new one */ - add_child(parent, chain, syms); + /* split the hits */ + new->hit = parent->hit; + new->val_nr = parent->val_nr - idx_local; + parent->val_nr = idx_local; + + /* create a new child for the new branch if any */ + if (idx_total < chain->nr) { + parent->hit = 0; + add_child(parent, chain, idx_total, syms); + } else { + parent->hit = 1; + } } static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, int start, struct symbol **syms); -static int +static void __append_chain_children(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms) + struct symbol **syms, int start) { struct callchain_node *rnode; /* lookup in childrens */ list_for_each_entry(rnode, &root->children, brothers) { - int ret = __append_chain(rnode, chain, root->val_nr, syms); + int ret = __append_chain(rnode, chain, start, syms); if (!ret) - return 0; + return; } - return -1; + /* nothing in children, add to the current node */ + add_child(root, chain, start, syms); } static int @@ -142,14 +190,22 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, int i = start; bool found = false; - /* lookup in the current node */ + /* + * Lookup in the current node + * If we have a symbol, then compare the start to match + * anywhere inside a function. + */ list_for_each_entry(cnode, &root->val, list) { - if (cnode->ip != chain->ips[i++]) + if (i == chain->nr) + break; + if (cnode->sym && syms[i]) { + if (cnode->sym->start != syms[i]->start) + break; + } else if (cnode->ip != chain->ips[i]) break; if (!found) found = true; - if (i == chain->nr) - break; + i++; } /* matches not, relay on the parent */ @@ -157,23 +213,25 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, return -1; /* we match only a part of the node. Split it and add the new chain */ - if (i < root->val_nr) { - split_add_child(root, chain, cnode, i, syms); + if (i - start < root->val_nr) { + split_add_child(root, chain, cnode, start, i - start, syms); return 0; } /* we match 100% of the path, increment the hit */ - if (i == root->val_nr) { + if (i - start == root->val_nr && i == chain->nr) { root->hit++; return 0; } - return __append_chain_children(root, chain, syms); + /* We match the node and still have a part remaining */ + __append_chain_children(root, chain, syms, i); + + return 0; } void append_chain(struct callchain_node *root, struct ip_callchain *chain, struct symbol **syms) { - if (__append_chain_children(root, chain, syms) == -1) - add_child(root, chain, syms); + __append_chain_children(root, chain, syms, 0); } -- GitLab From 0a456fc58fb8ef3c53d18297ab5cd5d2a70d146b Mon Sep 17 00:00:00 2001 From: Anton Blanchard <anton@samba.org> Date: Wed, 1 Jul 2009 13:07:01 +1000 Subject: [PATCH 0487/1002] powerpc/perf_counter: Enable alternate PR/HV bits for POWER7 POWER7 has the same PR/HV bit layout as POWER6, so set the flag. Signed-off-by: Anton Blanchard <anton@samba.org> Acked-by: Paul Mackerras <paulus@samba.org> Cc: a.p.zijlstra@chello.nl Cc: benh@kernel.crashing.org LKML-Reference: <20090701030701.GI3563@kryten> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/powerpc/kernel/power7-pmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c index 5d755ef7ac8f2..5a9f5cbd40a48 100644 --- a/arch/powerpc/kernel/power7-pmu.c +++ b/arch/powerpc/kernel/power7-pmu.c @@ -358,6 +358,7 @@ static struct power_pmu power7_pmu = { .get_constraint = power7_get_constraint, .get_alternatives = power7_get_alternatives, .disable_pmc = power7_disable_pmc, + .flags = PPMU_ALT_SIPR, .n_generic = ARRAY_SIZE(power7_generic_events), .generic_events = power7_generic_events, .cache_events = &power7_cache_events, -- GitLab From 61c45981ddbd718136d49464f00d2f11938aaa6e Mon Sep 17 00:00:00 2001 From: Paul Mackerras <paulus@samba.org> Date: Wed, 1 Jul 2009 13:04:34 +1000 Subject: [PATCH 0488/1002] perf_counter tools: Rework event string parsing/syntax This reworks the parser for event descriptors to make it more consistent in what it accepts. It is now structured as a recursive descent parser for the following grammar: events ::= event ( ("," | space) space* event )* event ::= ( raw_event | numeric_event | symbolic_event | generic_hw_event ) [ event_modifier ] raw_event ::= "r" hex_number numeric_event ::= number ":" number number ::= decimal_number | "0x" hex_number | "0" octal_number symbolic_event ::= string_from_event_symbols_array generic_hw_event::= cache_type ( "-" ( cache_op | cache_result ) )* event_modifier ::= ":" ( "u" | "k" | "h" )+ with the extra restriction that you can have at most one cache_op and at most one cache_result. We pass the current string pointer by reference (i.e. as a const char **) to the various parsing functions so that they can advance the pointer to indicate how much they consumed. They return 0 if they didn't recognize the thing at the pointer or 1 if they did (and advance the pointer past it). This also fixes parse_aliases to take the longest matching alias from the table, not the first one. Otherwise "l1-data" would match the "l1-d" alias and the "ata" would not be consumed. This allows event modifiers indicating what processor modes to count in to be applied to any event, not just numeric events, and adds a ":h" modifier to indicate counting in hypervisor mode. Specifying ":u" now sets both exclude_kernel and exclude_hv, and so on. Multiple modes can be specified, e.g. ":uk" will count in user or hypervisor mode (i.e. only exclude_kernel will be set). Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <19018.53826.843815.189847@cargo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 232 +++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 72 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4d042f104cdcf..e6b83a3311a56 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -184,16 +184,20 @@ char *event_name(int counter) return "unknown"; } -static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) +static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size) { int i, j; + int n, longest = -1; for (i = 0; i < size; i++) { - for (j = 0; j < MAX_ALIASES; j++) { - if (!names[i][j]) - break; - if (strcasestr(str, names[i][j])) - return i; + for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { + n = strlen(names[i][j]); + if (n > longest && !strncasecmp(*str, names[i][j], n)) + longest = n; + } + if (longest > 0) { + *str += longest; + return i; } } @@ -201,30 +205,53 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) } static int -parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) +parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) { - int cache_type = -1, cache_op = 0, cache_result = 0; + const char *s = *str; + int cache_type = -1, cache_op = -1, cache_result = -1; - cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); + cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); /* * No fallback - if we cannot get a clear cache type * then bail out: */ if (cache_type == -1) - return -EINVAL; + return 0; + + while ((cache_op == -1 || cache_result == -1) && *s == '-') { + ++s; + + if (cache_op == -1) { + cache_op = parse_aliases(&s, hw_cache_op, + PERF_COUNT_HW_CACHE_OP_MAX); + if (cache_op >= 0) { + if (!is_cache_op_valid(cache_type, cache_op)) + return 0; + continue; + } + } + + if (cache_result == -1) { + cache_result = parse_aliases(&s, hw_cache_result, + PERF_COUNT_HW_CACHE_RESULT_MAX); + if (cache_result >= 0) + continue; + } + + /* + * Can't parse this as a cache op or result, so back up + * to the '-'. + */ + --s; + break; + } - cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX); /* * Fall back to reads: */ if (cache_op == -1) cache_op = PERF_COUNT_HW_CACHE_OP_READ; - if (!is_cache_op_valid(cache_type, cache_op)) - return -EINVAL; - - cache_result = parse_aliases(str, hw_cache_result, - PERF_COUNT_HW_CACHE_RESULT_MAX); /* * Fall back to accesses: */ @@ -234,93 +261,154 @@ parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) attr->config = cache_type | (cache_op << 8) | (cache_result << 16); attr->type = PERF_TYPE_HW_CACHE; - return 0; + *str = s; + return 1; } static int check_events(const char *str, unsigned int i) { - if (!strncmp(str, event_symbols[i].symbol, - strlen(event_symbols[i].symbol))) - return 1; + int n; - if (strlen(event_symbols[i].alias)) - if (!strncmp(str, event_symbols[i].alias, - strlen(event_symbols[i].alias))) - return 1; + n = strlen(event_symbols[i].symbol); + if (!strncmp(str, event_symbols[i].symbol, n)) + return n; + + n = strlen(event_symbols[i].alias); + if (n) + if (!strncmp(str, event_symbols[i].alias, n)) + return n; return 0; } -/* - * Each event can have multiple symbolic names. - * Symbolic names are (almost) exactly matched. - */ -static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) +static int +parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) { - u64 config, id; - int type; + const char *str = *strp; unsigned int i; - const char *sep, *pstr; + int n; - if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { - attr->type = PERF_TYPE_RAW; - attr->config = config; + for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { + n = check_events(str, i); + if (n > 0) { + attr->type = event_symbols[i].type; + attr->config = event_symbols[i].config; + *strp = str + n; + return 1; + } + } + return 0; +} + +static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + u64 config; + int n; + if (*str != 'r') return 0; + n = hex2u64(str + 1, &config); + if (n > 0) { + *strp = str + n + 1; + attr->type = PERF_TYPE_RAW; + attr->config = config; + return 1; } + return 0; +} - pstr = str; - sep = strchr(pstr, ':'); - if (sep) { - type = atoi(pstr); - pstr = sep + 1; - id = atoi(pstr); - sep = strchr(pstr, ':'); - if (sep) { - pstr = sep + 1; - if (strchr(pstr, 'k')) - attr->exclude_user = 1; - if (strchr(pstr, 'u')) - attr->exclude_kernel = 1; +static int +parse_numeric_event(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + char *endp; + unsigned long type; + u64 config; + + type = strtoul(str, &endp, 0); + if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { + str = endp + 1; + config = strtoul(str, &endp, 0); + if (endp > str) { + attr->type = type; + attr->config = config; + *strp = endp; + return 1; } - attr->type = type; - attr->config = id; + } + return 0; +} + +static int +parse_event_modifier(const char **strp, struct perf_counter_attr *attr) +{ + const char *str = *strp; + int eu = 1, ek = 1, eh = 1; + if (*str++ != ':') return 0; + while (*str) { + if (*str == 'u') + eu = 0; + else if (*str == 'k') + ek = 0; + else if (*str == 'h') + eh = 0; + else + break; + ++str; } + if (str >= *strp + 2) { + *strp = str; + attr->exclude_user = eu; + attr->exclude_kernel = ek; + attr->exclude_hv = eh; + return 1; + } + return 0; +} - for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { - if (check_events(str, i)) { - attr->type = event_symbols[i].type; - attr->config = event_symbols[i].config; +/* + * Each event can have multiple symbolic names. + * Symbolic names are (almost) exactly matched. + */ +static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) +{ + if (!(parse_raw_event(str, attr) || + parse_numeric_event(str, attr) || + parse_symbolic_event(str, attr) || + parse_generic_hw_event(str, attr))) + return 0; - return 0; - } - } + parse_event_modifier(str, attr); - return parse_generic_hw_symbols(str, attr); + return 1; } int parse_events(const struct option *opt, const char *str, int unset) { struct perf_counter_attr attr; - int ret; - memset(&attr, 0, sizeof(attr)); -again: - if (nr_counters == MAX_COUNTERS) - return -1; + for (;;) { + if (nr_counters == MAX_COUNTERS) + return -1; + + memset(&attr, 0, sizeof(attr)); + if (!parse_event_symbols(&str, &attr)) + return -1; - ret = parse_event_symbols(str, &attr); - if (ret < 0) - return ret; + if (!(*str == 0 || *str == ',' || isspace(*str))) + return -1; - attrs[nr_counters] = attr; - nr_counters++; + attrs[nr_counters] = attr; + nr_counters++; - str = strstr(str, ","); - if (str) { - str++; - goto again; + if (*str == 0) + break; + if (*str == ',') + ++str; + while (isspace(*str)) + ++str; } return 0; -- GitLab From 4a2bb6fcc80e6330ca2f2393e98605052cc7780b Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu <mhiramat@redhat.com> Date: Tue, 30 Jun 2009 17:08:09 -0400 Subject: [PATCH 0489/1002] kprobes: No need to unlock kprobe_insn_mutex Remove needless kprobe_insn_mutex unlocking during safety check in garbage collection, because if someone releases a dirty slot during safety check (which ensures other cpus doesn't execute all dirty slots), the safety check must be fail. So, we need to hold the mutex while checking safety. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> LKML-Reference: <20090630210809.17851.28781.stgit@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/kprobes.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index c0fa54b276d95..16b5739c516aa 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -237,13 +237,9 @@ static int __kprobes collect_garbage_slots(void) { struct kprobe_insn_page *kip; struct hlist_node *pos, *next; - int safety; /* Ensure no-one is preepmted on the garbages */ - mutex_unlock(&kprobe_insn_mutex); - safety = check_safety(); - mutex_lock(&kprobe_insn_mutex); - if (safety != 0) + if (check_safety()) return -EAGAIN; hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) { -- GitLab From 61fd21670d048017c81e62f60894ef1b04b481db Mon Sep 17 00:00:00 2001 From: Andre Noll <maan@systemlinux.org> Date: Thu, 25 Jun 2009 13:03:04 +0200 Subject: [PATCH 0490/1002] Trivial typo fixes in Documentation/block/data-integrity.txt. Signed-off-by: Andre Noll <maan@systemlinux.org> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- Documentation/block/data-integrity.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/block/data-integrity.txt b/Documentation/block/data-integrity.txt index e8ca040ba2cff..2d735b0ae383b 100644 --- a/Documentation/block/data-integrity.txt +++ b/Documentation/block/data-integrity.txt @@ -50,7 +50,7 @@ encouraged them to allow separation of the data and integrity metadata scatter-gather lists. The controller will interleave the buffers on write and split them on -read. This means that the Linux can DMA the data buffers to and from +read. This means that Linux can DMA the data buffers to and from host memory without changes to the page cache. Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs @@ -66,7 +66,7 @@ software RAID5). The IP checksum is weaker than the CRC in terms of detecting bit errors. However, the strength is really in the separation of the data -buffers and the integrity metadata. These two distinct buffers much +buffers and the integrity metadata. These two distinct buffers must match up for an I/O to complete. The separation of the data and integrity metadata buffers as well as -- GitLab From d5036d770f871bd34c9cfd955e6dee692e1e8e81 Mon Sep 17 00:00:00 2001 From: Jens Axboe <jens.axboe@oracle.com> Date: Fri, 26 Jun 2009 10:44:34 +0200 Subject: [PATCH 0491/1002] cfq-iosched: move cfqq initialization out of cfq_find_alloc_queue() We're going to be needing that init code outside of that function to get rid of the __GFP_NOFAIL in cfqq allocation. Reviewed-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/cfq-iosched.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 833ec18eaa63e..c760ae7019dda 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1641,6 +1641,26 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc) ioc->ioprio_changed = 0; } +static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, + pid_t pid, int is_sync) +{ + RB_CLEAR_NODE(&cfqq->rb_node); + RB_CLEAR_NODE(&cfqq->p_node); + INIT_LIST_HEAD(&cfqq->fifo); + + atomic_set(&cfqq->ref, 0); + cfqq->cfqd = cfqd; + + cfq_mark_cfqq_prio_changed(cfqq); + + if (is_sync) { + if (!cfq_class_idle(cfqq)) + cfq_mark_cfqq_idle_window(cfqq); + cfq_mark_cfqq_sync(cfqq); + } + cfqq->pid = pid; +} + static struct cfq_queue * cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, gfp_t gfp_mask) @@ -1678,23 +1698,8 @@ cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, goto out; } - RB_CLEAR_NODE(&cfqq->rb_node); - RB_CLEAR_NODE(&cfqq->p_node); - INIT_LIST_HEAD(&cfqq->fifo); - - atomic_set(&cfqq->ref, 0); - cfqq->cfqd = cfqd; - - cfq_mark_cfqq_prio_changed(cfqq); - + cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync); cfq_init_prio_data(cfqq, ioc); - - if (is_sync) { - if (!cfq_class_idle(cfqq)) - cfq_mark_cfqq_idle_window(cfqq); - cfq_mark_cfqq_sync(cfqq); - } - cfqq->pid = current->pid; cfq_log_cfqq(cfqd, cfqq, "alloced"); } -- GitLab From 6118b70b3a0b4c583439bb77600194c82f220ce3 Mon Sep 17 00:00:00 2001 From: Jens Axboe <jens.axboe@oracle.com> Date: Tue, 30 Jun 2009 09:34:12 +0200 Subject: [PATCH 0492/1002] cfq-iosched: get rid of the need for __GFP_NOFAIL in cfq_find_alloc_queue() Setup an emergency fallback cfqq that we allocate at IO scheduler init time. If the slab allocation fails in cfq_find_alloc_queue(), we'll just punt IO to that cfqq instead. This ensures that cfq_find_alloc_queue() never fails without having to ensure free memory. On cfqq lookup, always try to allocate a new cfqq if the given cfq io context has the oom_cfqq assigned. This ensures that we only temporarily punt to this shared queue. Reviewed-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/cfq-iosched.c | 137 +++++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index c760ae7019dda..1d9160ffa26dd 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -70,6 +70,51 @@ struct cfq_rb_root { }; #define CFQ_RB_ROOT (struct cfq_rb_root) { RB_ROOT, NULL, } +/* + * Per process-grouping structure + */ +struct cfq_queue { + /* reference count */ + atomic_t ref; + /* various state flags, see below */ + unsigned int flags; + /* parent cfq_data */ + struct cfq_data *cfqd; + /* service_tree member */ + struct rb_node rb_node; + /* service_tree key */ + unsigned long rb_key; + /* prio tree member */ + struct rb_node p_node; + /* prio tree root we belong to, if any */ + struct rb_root *p_root; + /* sorted list of pending requests */ + struct rb_root sort_list; + /* if fifo isn't expired, next request to serve */ + struct request *next_rq; + /* requests queued in sort_list */ + int queued[2]; + /* currently allocated requests */ + int allocated[2]; + /* fifo list of requests in sort_list */ + struct list_head fifo; + + unsigned long slice_end; + long slice_resid; + unsigned int slice_dispatch; + + /* pending metadata requests */ + int meta_pending; + /* number of requests that are on the dispatch list or inside driver */ + int dispatched; + + /* io prio of this group */ + unsigned short ioprio, org_ioprio; + unsigned short ioprio_class, org_ioprio_class; + + pid_t pid; +}; + /* * Per block device queue structure */ @@ -135,51 +180,11 @@ struct cfq_data { unsigned int cfq_slice_idle; struct list_head cic_list; -}; -/* - * Per process-grouping structure - */ -struct cfq_queue { - /* reference count */ - atomic_t ref; - /* various state flags, see below */ - unsigned int flags; - /* parent cfq_data */ - struct cfq_data *cfqd; - /* service_tree member */ - struct rb_node rb_node; - /* service_tree key */ - unsigned long rb_key; - /* prio tree member */ - struct rb_node p_node; - /* prio tree root we belong to, if any */ - struct rb_root *p_root; - /* sorted list of pending requests */ - struct rb_root sort_list; - /* if fifo isn't expired, next request to serve */ - struct request *next_rq; - /* requests queued in sort_list */ - int queued[2]; - /* currently allocated requests */ - int allocated[2]; - /* fifo list of requests in sort_list */ - struct list_head fifo; - - unsigned long slice_end; - long slice_resid; - unsigned int slice_dispatch; - - /* pending metadata requests */ - int meta_pending; - /* number of requests that are on the dispatch list or inside driver */ - int dispatched; - - /* io prio of this group */ - unsigned short ioprio, org_ioprio; - unsigned short ioprio_class, org_ioprio_class; - - pid_t pid; + /* + * Fallback dummy cfqq for extreme OOM conditions + */ + struct cfq_queue oom_cfqq; }; enum cfqq_state_flags { @@ -1673,41 +1678,40 @@ cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, /* cic always exists here */ cfqq = cic_to_cfqq(cic, is_sync); - if (!cfqq) { + /* + * Always try a new alloc if we fell back to the OOM cfqq + * originally, since it should just be a temporary situation. + */ + if (!cfqq || cfqq == &cfqd->oom_cfqq) { + cfqq = NULL; if (new_cfqq) { cfqq = new_cfqq; new_cfqq = NULL; } else if (gfp_mask & __GFP_WAIT) { - /* - * Inform the allocator of the fact that we will - * just repeat this allocation if it fails, to allow - * the allocator to do whatever it needs to attempt to - * free memory. - */ spin_unlock_irq(cfqd->queue->queue_lock); new_cfqq = kmem_cache_alloc_node(cfq_pool, - gfp_mask | __GFP_NOFAIL | __GFP_ZERO, + gfp_mask | __GFP_ZERO, cfqd->queue->node); spin_lock_irq(cfqd->queue->queue_lock); - goto retry; + if (new_cfqq) + goto retry; } else { cfqq = kmem_cache_alloc_node(cfq_pool, gfp_mask | __GFP_ZERO, cfqd->queue->node); - if (!cfqq) - goto out; } - cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync); - cfq_init_prio_data(cfqq, ioc); - cfq_log_cfqq(cfqd, cfqq, "alloced"); + if (cfqq) { + cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync); + cfq_init_prio_data(cfqq, ioc); + cfq_log_cfqq(cfqd, cfqq, "alloced"); + } else + cfqq = &cfqd->oom_cfqq; } if (new_cfqq) kmem_cache_free(cfq_pool, new_cfqq); -out: - WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); return cfqq; } @@ -1740,11 +1744,8 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, cfqq = *async_cfqq; } - if (!cfqq) { + if (!cfqq) cfqq = cfq_find_alloc_queue(cfqd, is_sync, ioc, gfp_mask); - if (!cfqq) - return NULL; - } /* * pin the queue now that it's allocated, scheduler exit will prune it @@ -2470,6 +2471,14 @@ static void *cfq_init_queue(struct request_queue *q) for (i = 0; i < CFQ_PRIO_LISTS; i++) cfqd->prio_trees[i] = RB_ROOT; + /* + * Our fallback cfqq if cfq_find_alloc_queue() runs into OOM issues. + * Grab a permanent reference to it, so that the normal code flow + * will not attempt to free it. + */ + cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0); + atomic_inc(&cfqd->oom_cfqq.ref); + INIT_LIST_HEAD(&cfqd->cic_list); cfqd->queue = q; -- GitLab From 7878cba9f0037f5599004b03a1260b32d9050360 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" <martin.petersen@oracle.com> Date: Fri, 26 Jun 2009 15:37:49 +0200 Subject: [PATCH 0493/1002] block: Create bip slabs with embedded integrity vectors This patch restores stacking ability to the block layer integrity infrastructure by creating a set of dedicated bip slabs. Each bip slab has an embedded bio_vec array at the end. This cuts down on memory allocations and also simplifies the code compared to the original bvec version. Only the largest bip slab is backed by a mempool. The pool is contained in the bio_set so stacking drivers can ensure forward progress. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Jens Axboe <axboe@carl.(none)> --- block/blk-core.c | 2 +- drivers/md/dm.c | 4 +- fs/bio-integrity.c | 170 ++++++++++++++++++++++++++++++++------------ fs/bio.c | 11 ++- include/linux/bio.h | 22 ++++-- 5 files changed, 152 insertions(+), 57 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index b06cf5c2a829c..345d99da8d415 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2365,7 +2365,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src, __bio_clone(bio, bio_src); if (bio_integrity(bio_src) && - bio_integrity_clone(bio, bio_src, gfp_mask)) + bio_integrity_clone(bio, bio_src, gfp_mask, bs)) goto free_and_out; if (bio_ctr && bio_ctr(bio, bio_src, data)) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 3c6d4ee8921d2..9acd54a5cffb3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1017,7 +1017,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, clone->bi_flags |= 1 << BIO_CLONED; if (bio_integrity(bio)) { - bio_integrity_clone(clone, bio, GFP_NOIO); + bio_integrity_clone(clone, bio, GFP_NOIO, bs); bio_integrity_trim(clone, bio_sector_offset(bio, idx, offset), len); } @@ -1045,7 +1045,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, clone->bi_flags &= ~(1 << BIO_SEG_VALID); if (bio_integrity(bio)) { - bio_integrity_clone(clone, bio, GFP_NOIO); + bio_integrity_clone(clone, bio, GFP_NOIO, bs); if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) bio_integrity_trim(clone, diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 31c46a241bac6..49a34e7f7306d 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -1,7 +1,7 @@ /* * bio-integrity.c - bio data integrity extensions * - * Copyright (C) 2007, 2008 Oracle Corporation + * Copyright (C) 2007, 2008, 2009 Oracle Corporation * Written by: Martin K. Petersen <martin.petersen@oracle.com> * * This program is free software; you can redistribute it and/or @@ -25,63 +25,121 @@ #include <linux/bio.h> #include <linux/workqueue.h> -static struct kmem_cache *bio_integrity_slab __read_mostly; -static mempool_t *bio_integrity_pool; -static struct bio_set *integrity_bio_set; +struct integrity_slab { + struct kmem_cache *slab; + unsigned short nr_vecs; + char name[8]; +}; + +#define IS(x) { .nr_vecs = x, .name = "bip-"__stringify(x) } +struct integrity_slab bip_slab[BIOVEC_NR_POOLS] __read_mostly = { + IS(1), IS(4), IS(16), IS(64), IS(128), IS(BIO_MAX_PAGES), +}; +#undef IS + static struct workqueue_struct *kintegrityd_wq; +static inline unsigned int vecs_to_idx(unsigned int nr) +{ + switch (nr) { + case 1: + return 0; + case 2 ... 4: + return 1; + case 5 ... 16: + return 2; + case 17 ... 64: + return 3; + case 65 ... 128: + return 4; + case 129 ... BIO_MAX_PAGES: + return 5; + default: + BUG(); + } +} + +static inline int use_bip_pool(unsigned int idx) +{ + if (idx == BIOVEC_NR_POOLS) + return 1; + + return 0; +} + /** - * bio_integrity_alloc - Allocate integrity payload and attach it to bio + * bio_integrity_alloc_bioset - Allocate integrity payload and attach it to bio * @bio: bio to attach integrity metadata to * @gfp_mask: Memory allocation mask * @nr_vecs: Number of integrity metadata scatter-gather elements + * @bs: bio_set to allocate from * * Description: This function prepares a bio for attaching integrity * metadata. nr_vecs specifies the maximum number of pages containing * integrity metadata that can be attached. */ -struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, - gfp_t gfp_mask, - unsigned int nr_vecs) +struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio, + gfp_t gfp_mask, + unsigned int nr_vecs, + struct bio_set *bs) { struct bio_integrity_payload *bip; - struct bio_vec *iv; - unsigned long idx; + unsigned int idx = vecs_to_idx(nr_vecs); BUG_ON(bio == NULL); + bip = NULL; - bip = mempool_alloc(bio_integrity_pool, gfp_mask); - if (unlikely(bip == NULL)) { - printk(KERN_ERR "%s: could not alloc bip\n", __func__); - return NULL; - } + /* Lower order allocations come straight from slab */ + if (!use_bip_pool(idx)) + bip = kmem_cache_alloc(bip_slab[idx].slab, gfp_mask); - memset(bip, 0, sizeof(*bip)); + /* Use mempool if lower order alloc failed or max vecs were requested */ + if (bip == NULL) { + bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask); - iv = bvec_alloc_bs(gfp_mask, nr_vecs, &idx, integrity_bio_set); - if (unlikely(iv == NULL)) { - printk(KERN_ERR "%s: could not alloc bip_vec\n", __func__); - mempool_free(bip, bio_integrity_pool); - return NULL; + if (unlikely(bip == NULL)) { + printk(KERN_ERR "%s: could not alloc bip\n", __func__); + return NULL; + } } - bip->bip_pool = idx; - bip->bip_vec = iv; + memset(bip, 0, sizeof(*bip)); + + bip->bip_slab = idx; bip->bip_bio = bio; bio->bi_integrity = bip; return bip; } +EXPORT_SYMBOL(bio_integrity_alloc_bioset); + +/** + * bio_integrity_alloc - Allocate integrity payload and attach it to bio + * @bio: bio to attach integrity metadata to + * @gfp_mask: Memory allocation mask + * @nr_vecs: Number of integrity metadata scatter-gather elements + * + * Description: This function prepares a bio for attaching integrity + * metadata. nr_vecs specifies the maximum number of pages containing + * integrity metadata that can be attached. + */ +struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, + gfp_t gfp_mask, + unsigned int nr_vecs) +{ + return bio_integrity_alloc_bioset(bio, gfp_mask, nr_vecs, fs_bio_set); +} EXPORT_SYMBOL(bio_integrity_alloc); /** * bio_integrity_free - Free bio integrity payload * @bio: bio containing bip to be freed + * @bs: bio_set this bio was allocated from * * Description: Used to free the integrity portion of a bio. Usually * called from bio_free(). */ -void bio_integrity_free(struct bio *bio) +void bio_integrity_free(struct bio *bio, struct bio_set *bs) { struct bio_integrity_payload *bip = bio->bi_integrity; @@ -92,8 +150,10 @@ void bio_integrity_free(struct bio *bio) && bip->bip_buf != NULL) kfree(bip->bip_buf); - bvec_free_bs(integrity_bio_set, bip->bip_vec, bip->bip_pool); - mempool_free(bip, bio_integrity_pool); + if (use_bip_pool(bip->bip_slab)) + mempool_free(bip, bs->bio_integrity_pool); + else + kmem_cache_free(bip_slab[bip->bip_slab].slab, bip); bio->bi_integrity = NULL; } @@ -114,7 +174,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, struct bio_integrity_payload *bip = bio->bi_integrity; struct bio_vec *iv; - if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_pool)) { + if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) { printk(KERN_ERR "%s: bip_vec full\n", __func__); return 0; } @@ -647,8 +707,8 @@ void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors) bp->iv1 = bip->bip_vec[0]; bp->iv2 = bip->bip_vec[0]; - bp->bip1.bip_vec = &bp->iv1; - bp->bip2.bip_vec = &bp->iv2; + bp->bip1.bip_vec[0] = bp->iv1; + bp->bip2.bip_vec[0] = bp->iv2; bp->iv1.bv_len = sectors * bi->tuple_size; bp->iv2.bv_offset += sectors * bi->tuple_size; @@ -667,17 +727,19 @@ EXPORT_SYMBOL(bio_integrity_split); * @bio: New bio * @bio_src: Original bio * @gfp_mask: Memory allocation mask + * @bs: bio_set to allocate bip from * * Description: Called to allocate a bip when cloning a bio */ -int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask) +int bio_integrity_clone(struct bio *bio, struct bio *bio_src, + gfp_t gfp_mask, struct bio_set *bs) { struct bio_integrity_payload *bip_src = bio_src->bi_integrity; struct bio_integrity_payload *bip; BUG_ON(bip_src == NULL); - bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt); + bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs); if (bip == NULL) return -EIO; @@ -693,25 +755,43 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask) } EXPORT_SYMBOL(bio_integrity_clone); -static int __init bio_integrity_init(void) +int bioset_integrity_create(struct bio_set *bs, int pool_size) { - kintegrityd_wq = create_workqueue("kintegrityd"); + unsigned int max_slab = vecs_to_idx(BIO_MAX_PAGES); + + bs->bio_integrity_pool = + mempool_create_slab_pool(pool_size, bip_slab[max_slab].slab); + if (!bs->bio_integrity_pool) + return -1; + + return 0; +} +EXPORT_SYMBOL(bioset_integrity_create); + +void bioset_integrity_free(struct bio_set *bs) +{ + if (bs->bio_integrity_pool) + mempool_destroy(bs->bio_integrity_pool); +} +EXPORT_SYMBOL(bioset_integrity_free); + +void __init bio_integrity_init(void) +{ + unsigned int i; + + kintegrityd_wq = create_workqueue("kintegrityd"); if (!kintegrityd_wq) panic("Failed to create kintegrityd\n"); - bio_integrity_slab = KMEM_CACHE(bio_integrity_payload, - SLAB_HWCACHE_ALIGN|SLAB_PANIC); + for (i = 0 ; i < BIOVEC_NR_POOLS ; i++) { + unsigned int size; - bio_integrity_pool = mempool_create_slab_pool(BIO_POOL_SIZE, - bio_integrity_slab); - if (!bio_integrity_pool) - panic("bio_integrity: can't allocate bip pool\n"); + size = sizeof(struct bio_integrity_payload) + + bip_slab[i].nr_vecs * sizeof(struct bio_vec); - integrity_bio_set = bioset_create(BIO_POOL_SIZE, 0); - if (!integrity_bio_set) - panic("bio_integrity: can't allocate bio_set\n"); - - return 0; + bip_slab[i].slab = + kmem_cache_create(bip_slab[i].name, size, 0, + SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); + } } -subsys_initcall(bio_integrity_init); diff --git a/fs/bio.c b/fs/bio.c index 24c9140435323..1486b19fc4315 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -238,7 +238,7 @@ void bio_free(struct bio *bio, struct bio_set *bs) bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); if (bio_integrity(bio)) - bio_integrity_free(bio); + bio_integrity_free(bio, bs); /* * If we have front padding, adjust the bio pointer before freeing @@ -341,7 +341,7 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) static void bio_kmalloc_destructor(struct bio *bio) { if (bio_integrity(bio)) - bio_integrity_free(bio); + bio_integrity_free(bio, fs_bio_set); kfree(bio); } @@ -472,7 +472,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) if (bio_integrity(bio)) { int ret; - ret = bio_integrity_clone(b, bio, gfp_mask); + ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set); if (ret < 0) { bio_put(b); @@ -1539,6 +1539,7 @@ void bioset_free(struct bio_set *bs) if (bs->bio_pool) mempool_destroy(bs->bio_pool); + bioset_integrity_free(bs); biovec_free_pools(bs); bio_put_slab(bs); @@ -1579,6 +1580,9 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) if (!bs->bio_pool) goto bad; + if (bioset_integrity_create(bs, pool_size)) + goto bad; + if (!biovec_create_pools(bs, pool_size)) return bs; @@ -1616,6 +1620,7 @@ static int __init init_bio(void) if (!bio_slabs) panic("bio: can't allocate bios\n"); + bio_integrity_init(); biovec_init_slabs(); fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); diff --git a/include/linux/bio.h b/include/linux/bio.h index 2a04eb54c0dd0..2892b710771c5 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -319,7 +319,6 @@ static inline int bio_has_allocated_vec(struct bio *bio) */ struct bio_integrity_payload { struct bio *bip_bio; /* parent bio */ - struct bio_vec *bip_vec; /* integrity data vector */ sector_t bip_sector; /* virtual start sector */ @@ -328,11 +327,12 @@ struct bio_integrity_payload { unsigned int bip_size; - unsigned short bip_pool; /* pool the ivec came from */ + unsigned short bip_slab; /* slab the bip came from */ unsigned short bip_vcnt; /* # of integrity bio_vecs */ unsigned short bip_idx; /* current bip_vec index */ struct work_struct bip_work; /* I/O completion */ + struct bio_vec bip_vec[0]; /* embedded bvec array */ }; #endif /* CONFIG_BLK_DEV_INTEGRITY */ @@ -430,6 +430,9 @@ struct bio_set { unsigned int front_pad; mempool_t *bio_pool; +#if defined(CONFIG_BLK_DEV_INTEGRITY) + mempool_t *bio_integrity_pool; +#endif mempool_t *bvec_pool; }; @@ -634,8 +637,9 @@ static inline struct bio *bio_list_get(struct bio_list *bl) #define bio_integrity(bio) (bio->bi_integrity != NULL) +extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); -extern void bio_integrity_free(struct bio *); +extern void bio_integrity_free(struct bio *, struct bio_set *); extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int); extern int bio_integrity_enabled(struct bio *bio); extern int bio_integrity_set_tag(struct bio *, void *, unsigned int); @@ -645,21 +649,27 @@ extern void bio_integrity_endio(struct bio *, int); extern void bio_integrity_advance(struct bio *, unsigned int); extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int); extern void bio_integrity_split(struct bio *, struct bio_pair *, int); -extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t); +extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *); +extern int bioset_integrity_create(struct bio_set *, int); +extern void bioset_integrity_free(struct bio_set *); +extern void bio_integrity_init(void); #else /* CONFIG_BLK_DEV_INTEGRITY */ #define bio_integrity(a) (0) +#define bioset_integrity_create(a, b) (0) #define bio_integrity_prep(a) (0) #define bio_integrity_enabled(a) (0) -#define bio_integrity_clone(a, b, c) (0) -#define bio_integrity_free(a) do { } while (0) +#define bio_integrity_clone(a, b, c, d) (0) +#define bioset_integrity_free(a) do { } while (0) +#define bio_integrity_free(a, b) do { } while (0) #define bio_integrity_endio(a, b) do { } while (0) #define bio_integrity_advance(a, b) do { } while (0) #define bio_integrity_trim(a, b, c) do { } while (0) #define bio_integrity_split(a, b, c) do { } while (0) #define bio_integrity_set_tag(a, b, c) do { } while (0) #define bio_integrity_get_tag(a, b, c) do { } while (0) +#define bio_integrity_init(a) do { } while (0) #endif /* CONFIG_BLK_DEV_INTEGRITY */ -- GitLab From 018e0446890661504783f92388ecce7138c1566d Mon Sep 17 00:00:00 2001 From: Jens Axboe <jens.axboe@oracle.com> Date: Fri, 26 Jun 2009 16:27:10 +0200 Subject: [PATCH 0494/1002] block: get rid of queue-private command filter The initial patches to support this through sysfs export were broken and have been if 0'ed out in any release. So lets just kill the code and reclaim some space in struct request_queue, if anyone would later like to fixup the sysfs bits, the git history can easily restore the removed bits. Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/Makefile | 2 +- block/blk-core.c | 2 - block/bsg.c | 2 +- block/cmd-filter.c | 233 ----------------------------------------- block/scsi_ioctl.c | 43 +++++++- drivers/scsi/sg.c | 4 +- include/linux/blkdev.h | 15 +-- 7 files changed, 42 insertions(+), 259 deletions(-) delete mode 100644 block/cmd-filter.c diff --git a/block/Makefile b/block/Makefile index e9fa4dd690f23..6c54ed0ff755b 100644 --- a/block/Makefile +++ b/block/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \ blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \ blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \ - ioctl.o genhd.o scsi_ioctl.o cmd-filter.o + ioctl.o genhd.o scsi_ioctl.o obj-$(CONFIG_BLK_DEV_BSG) += bsg.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o diff --git a/block/blk-core.c b/block/blk-core.c index 345d99da8d415..02b87134a1678 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -595,8 +595,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) q->sg_reserved_size = INT_MAX; - blk_set_cmd_filter_defaults(&q->cmd_filter); - /* * all done */ diff --git a/block/bsg.c b/block/bsg.c index e7d4752542489..5f184bb3ff9e1 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -186,7 +186,7 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, return -EFAULT; if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { - if (blk_verify_command(&q->cmd_filter, rq->cmd, has_write_perm)) + if (blk_verify_command(rq->cmd, has_write_perm)) return -EPERM; } else if (!capable(CAP_SYS_RAWIO)) return -EPERM; diff --git a/block/cmd-filter.c b/block/cmd-filter.c deleted file mode 100644 index 572bbc2f900d8..0000000000000 --- a/block/cmd-filter.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2004 Peter M. Jones <pjones@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public Licens - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- - * - */ - -#include <linux/list.h> -#include <linux/genhd.h> -#include <linux/spinlock.h> -#include <linux/capability.h> -#include <linux/bitops.h> -#include <linux/blkdev.h> - -#include <scsi/scsi.h> -#include <linux/cdrom.h> - -int blk_verify_command(struct blk_cmd_filter *filter, - unsigned char *cmd, fmode_t has_write_perm) -{ - /* root can do any command. */ - if (capable(CAP_SYS_RAWIO)) - return 0; - - /* if there's no filter set, assume we're filtering everything out */ - if (!filter) - return -EPERM; - - /* Anybody who can open the device can do a read-safe command */ - if (test_bit(cmd[0], filter->read_ok)) - return 0; - - /* Write-safe commands require a writable open */ - if (test_bit(cmd[0], filter->write_ok) && has_write_perm) - return 0; - - return -EPERM; -} -EXPORT_SYMBOL(blk_verify_command); - -#if 0 -/* and now, the sysfs stuff */ -static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page, - int rw) -{ - char *npage = page; - unsigned long *okbits; - int i; - - if (rw == READ) - okbits = filter->read_ok; - else - okbits = filter->write_ok; - - for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) { - if (test_bit(i, okbits)) { - npage += sprintf(npage, "0x%02x", i); - if (i < BLK_SCSI_MAX_CMDS - 1) - sprintf(npage++, " "); - } - } - - if (npage != page) - npage += sprintf(npage, "\n"); - - return npage - page; -} - -static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page) -{ - return rcf_cmds_show(filter, page, READ); -} - -static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter, - char *page) -{ - return rcf_cmds_show(filter, page, WRITE); -} - -static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter, - const char *page, size_t count, int rw) -{ - unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits; - int cmd, set; - char *p, *status; - - if (rw == READ) { - memcpy(&okbits, filter->read_ok, sizeof(okbits)); - target_okbits = filter->read_ok; - } else { - memcpy(&okbits, filter->write_ok, sizeof(okbits)); - target_okbits = filter->write_ok; - } - - while ((p = strsep((char **)&page, " ")) != NULL) { - set = 1; - - if (p[0] == '+') { - p++; - } else if (p[0] == '-') { - set = 0; - p++; - } - - cmd = simple_strtol(p, &status, 16); - - /* either of these cases means invalid input, so do nothing. */ - if ((status == p) || cmd >= BLK_SCSI_MAX_CMDS) - return -EINVAL; - - if (set) - __set_bit(cmd, okbits); - else - __clear_bit(cmd, okbits); - } - - memcpy(target_okbits, okbits, sizeof(okbits)); - return count; -} - -static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter, - const char *page, size_t count) -{ - return rcf_cmds_store(filter, page, count, READ); -} - -static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter, - const char *page, size_t count) -{ - return rcf_cmds_store(filter, page, count, WRITE); -} - -struct rcf_sysfs_entry { - struct attribute attr; - ssize_t (*show)(struct blk_cmd_filter *, char *); - ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t); -}; - -static struct rcf_sysfs_entry rcf_readcmds_entry = { - .attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR }, - .show = rcf_readcmds_show, - .store = rcf_readcmds_store, -}; - -static struct rcf_sysfs_entry rcf_writecmds_entry = { - .attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR }, - .show = rcf_writecmds_show, - .store = rcf_writecmds_store, -}; - -static struct attribute *default_attrs[] = { - &rcf_readcmds_entry.attr, - &rcf_writecmds_entry.attr, - NULL, -}; - -#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr) - -static ssize_t -rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - struct rcf_sysfs_entry *entry = to_rcf(attr); - struct blk_cmd_filter *filter; - - filter = container_of(kobj, struct blk_cmd_filter, kobj); - if (entry->show) - return entry->show(filter, page); - - return 0; -} - -static ssize_t -rcf_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - struct rcf_sysfs_entry *entry = to_rcf(attr); - struct blk_cmd_filter *filter; - - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - if (!entry->store) - return -EINVAL; - - filter = container_of(kobj, struct blk_cmd_filter, kobj); - return entry->store(filter, page, length); -} - -static struct sysfs_ops rcf_sysfs_ops = { - .show = rcf_attr_show, - .store = rcf_attr_store, -}; - -static struct kobj_type rcf_ktype = { - .sysfs_ops = &rcf_sysfs_ops, - .default_attrs = default_attrs, -}; - -int blk_register_filter(struct gendisk *disk) -{ - int ret; - struct blk_cmd_filter *filter = &disk->queue->cmd_filter; - - ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, - &disk_to_dev(disk)->kobj, - "%s", "cmd_filter"); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL(blk_register_filter); - -void blk_unregister_filter(struct gendisk *disk) -{ - struct blk_cmd_filter *filter = &disk->queue->cmd_filter; - - kobject_put(&filter->kobj); -} -EXPORT_SYMBOL(blk_unregister_filter); -#endif diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 5f8e798ede4ee..f0e0ce0a607dc 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -32,6 +32,11 @@ #include <scsi/scsi_ioctl.h> #include <scsi/scsi_cmnd.h> +struct blk_cmd_filter { + unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; + unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; +} blk_default_cmd_filter; + /* Command group 3 is reserved and should never be used. */ const unsigned char scsi_command_size_tbl[8] = { @@ -105,7 +110,7 @@ static int sg_emulated_host(struct request_queue *q, int __user *p) return put_user(1, p); } -void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) +static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) { /* Basic read-only commands */ __set_bit(TEST_UNIT_READY, filter->read_ok); @@ -187,14 +192,37 @@ void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) __set_bit(GPCMD_SET_STREAMING, filter->write_ok); __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok); } -EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); + +int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm) +{ + struct blk_cmd_filter *filter = &blk_default_cmd_filter; + + /* root can do any command. */ + if (capable(CAP_SYS_RAWIO)) + return 0; + + /* if there's no filter set, assume we're filtering everything out */ + if (!filter) + return -EPERM; + + /* Anybody who can open the device can do a read-safe command */ + if (test_bit(cmd[0], filter->read_ok)) + return 0; + + /* Write-safe commands require a writable open */ + if (test_bit(cmd[0], filter->write_ok) && has_write_perm) + return 0; + + return -EPERM; +} +EXPORT_SYMBOL(blk_verify_command); static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, struct sg_io_hdr *hdr, fmode_t mode) { if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; - if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE)) + if (blk_verify_command(rq->cmd, mode & FMODE_WRITE)) return -EPERM; /* @@ -427,7 +455,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error; - err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE); + err = blk_verify_command(rq->cmd, mode & FMODE_WRITE); if (err) goto error; @@ -645,5 +673,10 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod blk_put_queue(q); return err; } - EXPORT_SYMBOL(scsi_cmd_ioctl); + +int __init blk_scsi_ioctl_init(void) +{ + blk_set_cmd_filter_defaults(&blk_default_cmd_filter); + return 0; +} diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8201387b4daa2..ef142fd47a834 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -210,13 +210,11 @@ static void sg_put_dev(Sg_device *sdp); static int sg_allow_access(struct file *filp, unsigned char *cmd) { struct sg_fd *sfp = (struct sg_fd *)filp->private_data; - struct request_queue *q = sfp->parentdp->device->request_queue; if (sfp->parentdp->device->type == TYPE_SCANNER) return 0; - return blk_verify_command(&q->cmd_filter, - cmd, filp->f_mode & FMODE_WRITE); + return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); } static int diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 8963d9149b5fc..49ae07951d554 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -301,12 +301,6 @@ struct blk_queue_tag { #define BLK_SCSI_MAX_CMDS (256) #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) -struct blk_cmd_filter { - unsigned long read_ok[BLK_SCSI_CMD_PER_LONG]; - unsigned long write_ok[BLK_SCSI_CMD_PER_LONG]; - struct kobject kobj; -}; - struct queue_limits { unsigned long bounce_pfn; unsigned long seg_boundary_mask; @@ -445,7 +439,6 @@ struct request_queue #if defined(CONFIG_BLK_DEV_BSG) struct bsg_class_device bsg_dev; #endif - struct blk_cmd_filter cmd_filter; }; #define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */ @@ -998,13 +991,7 @@ static inline int sb_issue_discard(struct super_block *sb, return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_KERNEL); } -/* -* command filter functions -*/ -extern int blk_verify_command(struct blk_cmd_filter *filter, - unsigned char *cmd, fmode_t has_write_perm); -extern void blk_unregister_filter(struct gendisk *disk); -extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter); +extern int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm); #define MAX_PHYS_SEGMENTS 128 #define MAX_HW_SEGMENTS 128 -- GitLab From db64f680ba4b5c56c4be59f0698000df89ff0281 Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@suse.de> Date: Tue, 30 Jun 2009 09:35:44 +0200 Subject: [PATCH 0495/1002] blocK: Restore barrier support for md and probably other virtual devices. The next_ordered flag is only meaningful for devices that use __make_request. So move the test against next_ordered out of generic code and in to __make_request Since this test was added, barriers have not worked on md or any devices that don't use __make_request and so don't bother to set next_ordered. (dm explicitly sets something other than QUEUE_ORDERED_NONE since commit 99360b4c18f7675b50d283301d46d755affe75fd but notes in the comments that it is otherwise meaningless). Cc: Ken Milmore <ken.milmore@googlemail.com> Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/blk-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 02b87134a1678..4b45435c6eaf2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1170,6 +1170,11 @@ static int __make_request(struct request_queue *q, struct bio *bio) const int unplug = bio_unplug(bio); int rw_flags; + if (bio_barrier(bio) && bio_has_data(bio) && + (q->next_ordered == QUEUE_ORDERED_NONE)) { + bio_endio(bio, -EOPNOTSUPP); + return 0; + } /* * low level driver can indicate that it wants pages above a * certain limit bounced to low memory (ie for highmem, or even @@ -1470,11 +1475,6 @@ static inline void __generic_make_request(struct bio *bio) err = -EOPNOTSUPP; goto end_io; } - if (bio_barrier(bio) && bio_has_data(bio) && - (q->next_ordered == QUEUE_ORDERED_NONE)) { - err = -EOPNOTSUPP; - goto end_io; - } ret = q->make_request_fn(q, bio); } while (ret); -- GitLab From 88a69dfbc6ab1e3b51bba8c9103055e21089ebb9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Wed, 1 Jul 2009 11:17:20 +0200 Subject: [PATCH 0496/1002] perf report: Fix HV bit mismerge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: builtin-report.c: In function ‘hist_entry__add’: builtin-report.c:1015: error: case label not within a switch statement builtin-report.c:1017: error: break statement not within loop or switch Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 197793051fa51..7d2b49adcdc55 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -964,6 +964,9 @@ resolve_callchain(struct thread *thread, struct map *map, } switch (context) { + case PERF_CONTEXT_HV: + dso = hypervisor_dso; + break; case PERF_CONTEXT_KERNEL: dso = kernel_dso; break; @@ -1012,9 +1015,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, }; int cmp; - case PERF_CONTEXT_HV: - dso = hypervisor_dso; - break; if ((sort__has_parent || callchain) && chain) syms = resolve_callchain(thread, map, chain, &entry); -- GitLab From a70c352a37671fe1ebcbd317b439aa4760f4ccb7 Mon Sep 17 00:00:00 2001 From: Pekka Enberg <penberg@cs.helsinki.fi> Date: Wed, 1 Jul 2009 11:51:18 +0300 Subject: [PATCH 0497/1002] xen: Use kcalloc() in xen_init_IRQ() The init_IRQ() function is now called with slab allocator initialized. Therefore, we must not use the bootmem allocator in xen_init_IRQ(). Fixes the following boot-time warning: ------------[ cut here ]------------ WARNING: at mm/bootmem.c:535 alloc_arch_preferred_bootmem+0x27/0x45() Modules linked in: Pid: 0, comm: swapper Not tainted 2.6.30 #1 Call Trace: [<ffffffff8102d6e3>] ? warn_slowpath_common+0x73/0xb0 [<ffffffff810210d9>] ? pvclock_clocksource_read+0x49/0x90 [<ffffffff812e522f>] ? alloc_arch_preferred_bootmem+0x27/0x45 [<ffffffff812e5761>] ? ___alloc_bootmem_nopanic+0x39/0xc9 [<ffffffff812e57fa>] ? ___alloc_bootmem+0x9/0x2f [<ffffffff812e9e21>] ? xen_init_IRQ+0x25/0x61 [<ffffffff812d69ee>] ? start_kernel+0x1b5/0x29e ---[ end trace 4eaa2a86a8e2da22 ]--- Acked-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Tested-by: Christian Kujau <lists@nerdbynature.de> Reported-by: Christian Kujau <lists@nerdbynature.de> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> Cc: lists@nerdbynature.de Cc: jeremy.fitzhardinge@citrix.com LKML-Reference: <1246438278.22417.28.camel@penberg-laptop> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- drivers/xen/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 891d2e90753ab..abad71b1632b1 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -927,9 +927,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { void __init xen_init_IRQ(void) { int i; - size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s); - cpu_evtchn_mask_p = alloc_bootmem(size); + cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s), + GFP_KERNEL); BUG_ON(cpu_evtchn_mask_p == NULL); init_evtchn_cpu_bindings(); -- GitLab From b706f64281b24d8b1fdc8ae883700131d365c412 Mon Sep 17 00:00:00 2001 From: Shan Wei <shanwei@cn.fujitsu.com> Date: Wed, 1 Jul 2009 12:41:14 +0200 Subject: [PATCH 0498/1002] cfq-iosched: remove redundant check for NULL cfqq in cfq_set_request() With the changes for falling back to an oom_cfqq, we never fail to find/allocate a queue in cfq_get_queue(). So remove the check. Signed-off-by: Shan Wei <shanwei@cn.fujitsu.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/cfq-iosched.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1d9160ffa26dd..87276eb83f7f5 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2313,10 +2313,6 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) cfqq = cic_to_cfqq(cic, is_sync); if (!cfqq) { cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask); - - if (!cfqq) - goto queue_fail; - cic_set_cfqq(cic, cfqq, is_sync); } -- GitLab From f37a291c527c954df4da568de718ebb36b8261c0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Wed, 1 Jul 2009 12:37:06 +0200 Subject: [PATCH 0499/1002] perf_counter tools: Add more warnings and fix/annotate them Enable -Wextra. This found a few real bugs plus a number of signed/unsigned type mismatches/uncleanlinesses. It also required a few annotations All things considered it was still worth it so lets try with this enabled for now. Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 2 +- tools/perf/builtin-annotate.c | 12 ++++----- tools/perf/builtin-help.c | 6 +++-- tools/perf/builtin-list.c | 2 +- tools/perf/builtin-record.c | 4 +-- tools/perf/builtin-report.c | 22 ++++++++-------- tools/perf/builtin-stat.c | 18 +++++++------ tools/perf/builtin-top.c | 8 +++--- tools/perf/perf.c | 5 +--- tools/perf/perf.h | 2 ++ tools/perf/util/alias.c | 2 +- tools/perf/util/cache.h | 1 + tools/perf/util/callchain.c | 15 ++++++----- tools/perf/util/callchain.h | 10 +++---- tools/perf/util/color.c | 10 ++++--- tools/perf/util/config.c | 18 +++++++------ tools/perf/util/exec_cmd.c | 5 +++- tools/perf/util/help.c | 26 +++++++++++-------- tools/perf/util/help.h | 6 ++--- tools/perf/util/parse-events.c | 2 +- tools/perf/util/parse-options.c | 2 +- tools/perf/util/parse-options.h | 25 +++++++++--------- tools/perf/util/quote.c | 46 ++++++++++++++++++--------------- tools/perf/util/quote.h | 2 +- tools/perf/util/strbuf.c | 13 +++++----- tools/perf/util/strbuf.h | 10 +++---- tools/perf/util/wrapper.c | 5 ++-- 27 files changed, 151 insertions(+), 128 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index f572c90f610ea..eddf076b19d7c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -164,7 +164,7 @@ endif # CFLAGS and LDFLAGS are for the users to override from the command line. -CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 +CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 LDFLAGS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) ALL_LDFLAGS = $(LDFLAGS) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 722c0f54e549e..6cba70daf1215 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -160,7 +160,7 @@ static void dsos__fprintf(FILE *fp) static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) { - return dso__find_symbol(kernel_dso, ip); + return dso__find_symbol(dso, ip); } static int load_kernel(void) @@ -203,7 +203,7 @@ static u64 map__map_ip(struct map *map, u64 ip) return ip - map->start + map->pgoff; } -static u64 vdso__map_ip(struct map *map, u64 ip) +static u64 vdso__map_ip(struct map *map __used, u64 ip) { return ip; } @@ -600,7 +600,7 @@ static LIST_HEAD(hist_entry__sort_list); static int sort_dimension__add(char *tok) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { struct sort_dimension *sd = &sort_dimensions[i]; @@ -1069,7 +1069,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) static const char *prev_color; unsigned int offset; size_t line_len; - u64 line_ip; + s64 line_ip; int ret; char *c; @@ -1428,7 +1428,7 @@ static int __cmd_annotate(void) head += size; - if (offset + head < stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; rc = EXIT_SUCCESS; @@ -1492,7 +1492,7 @@ static void setup_sorting(void) free(str); } -int cmd_annotate(int argc, const char **argv, const char *prefix) +int cmd_annotate(int argc, const char **argv, const char *prefix __used) { symbol__init(); diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 0f32dc3f3c4c7..2599d86a733b4 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -3,6 +3,7 @@ * * Builtin help command */ +#include "perf.h" #include "util/cache.h" #include "builtin.h" #include "util/exec_cmd.h" @@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds; void list_common_cmds_help(void) { - int i, longest = 0; + unsigned int i, longest = 0; for (i = 0; i < ARRAY_SIZE(common_cmds); i++) { if (longest < strlen(common_cmds[i].name)) @@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd) open_html(page_path.buf); } -int cmd_help(int argc, const char **argv, const char *prefix) +int cmd_help(int argc, const char **argv, const char *prefix __used) { const char *alias; + load_command_list("perf-", &main_cmds, &other_cmds); perf_config(perf_help_config, NULL); diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index fe60e37c96efc..f990fa8a35c9d 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -13,7 +13,7 @@ #include "util/parse-options.h" #include "util/parse-events.h" -int cmd_list(int argc, const char **argv, const char *prefix) +int cmd_list(int argc __used, const char **argv __used, const char *prefix __used) { print_events(); return 0; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d18546f37d7c5..4ef78a5e6f326 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -294,7 +294,7 @@ static void pid_synthesize_mmap_samples(pid_t pid) while (1) { char bf[BUFSIZ], *pbf = bf; struct mmap_event mmap_ev = { - .header.type = PERF_EVENT_MMAP, + .header = { .type = PERF_EVENT_MMAP }, }; int n; size_t size; @@ -650,7 +650,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_record(int argc, const char **argv, const char *prefix) +int cmd_record(int argc, const char **argv, const char *prefix __used) { int counter; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7d2b49adcdc55..007363db3b16a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -177,7 +177,7 @@ static void dsos__fprintf(FILE *fp) static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) { - return dso__find_symbol(kernel_dso, ip); + return dso__find_symbol(dso, ip); } static int load_kernel(void) @@ -239,7 +239,7 @@ static u64 map__map_ip(struct map *map, u64 ip) return ip - map->start + map->pgoff; } -static u64 vdso__map_ip(struct map *map, u64 ip) +static u64 vdso__map_ip(struct map *map __used, u64 ip) { return ip; } @@ -712,7 +712,7 @@ static LIST_HEAD(hist_entry__sort_list); static int sort_dimension__add(char *tok) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { struct sort_dimension *sd = &sort_dimensions[i]; @@ -801,7 +801,7 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) ret += fprintf(fp, " %s\n", chain->sym->name); else ret += fprintf(fp, " %p\n", - (void *)chain->ip); + (void *)(long)chain->ip); } return ret; @@ -938,12 +938,12 @@ static int call__match(struct symbol *sym) } static struct symbol ** -resolve_callchain(struct thread *thread, struct map *map, +resolve_callchain(struct thread *thread, struct map *map __used, struct ip_callchain *chain, struct hist_entry *entry) { - int i; - struct symbol **syms; u64 context = PERF_CONTEXT_MAX; + struct symbol **syms; + unsigned int i; if (callchain) { syms = calloc(chain->nr, sizeof(*syms)); @@ -1183,7 +1183,7 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) fprintf(fp, "# ........"); list_for_each_entry(se, &hist_entry__sort_list, list) { - int i; + unsigned int i; if (exclude_other && (se == &sort_parent)) continue; @@ -1271,7 +1271,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) (long long)period); if (sample_type & PERF_SAMPLE_CALLCHAIN) { - int i; + unsigned int i; chain = (void *)more_data; @@ -1667,7 +1667,7 @@ static int __cmd_report(void) if (offset + head >= header->data_offset + header->data_size) goto done; - if (offset + head < stat.st_size) + if (offset + head < (unsigned long)stat.st_size) goto more; done: @@ -1756,7 +1756,7 @@ static void setup_list(struct strlist **list, const char *list_str, } } -int cmd_report(int argc, const char **argv, const char *prefix) +int cmd_report(int argc, const char **argv, const char *prefix __used) { symbol__init(); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 2e03524a1de0a..095a90e012a17 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -64,7 +64,7 @@ static struct perf_counter_attr default_attrs[] = { static int system_wide = 0; static int verbose = 0; -static int nr_cpus = 0; +static unsigned int nr_cpus = 0; static int run_idx = 0; static int run_count = 1; @@ -108,7 +108,8 @@ static void create_perf_stat_counter(int counter, int pid) PERF_FORMAT_TOTAL_TIME_RUNNING; if (system_wide) { - int cpu; + unsigned int cpu; + for (cpu = 0; cpu < nr_cpus; cpu++) { fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); if (fd[cpu][counter] < 0 && verbose) @@ -150,8 +151,8 @@ static inline int nsec_counter(int counter) static void read_counter(int counter) { u64 *count, single_count[3]; - ssize_t res; - int cpu, nv; + unsigned int cpu; + size_t res, nv; int scaled; count = event_res[run_idx][counter]; @@ -165,6 +166,7 @@ static void read_counter(int counter) res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); assert(res == nv * sizeof(u64)); + close(fd[cpu][counter]); fd[cpu][counter] = -1; @@ -200,7 +202,7 @@ static void read_counter(int counter) runtime_cycles[run_idx] = count[0]; } -static int run_perf_stat(int argc, const char **argv) +static int run_perf_stat(int argc __used, const char **argv) { unsigned long long t0, t1; int status = 0; @@ -390,7 +392,7 @@ static void calc_avg(void) event_res_avg[j]+1, event_res[i][j]+1); update_avg("counter/2", j, event_res_avg[j]+2, event_res[i][j]+2); - if (event_scaled[i][j] != -1) + if (event_scaled[i][j] != (u64)-1) update_avg("scaled", j, event_scaled_avg + j, event_scaled[i]+j); else @@ -510,7 +512,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_stat(int argc, const char **argv, const char *prefix) +int cmd_stat(int argc, const char **argv, const char *prefix __used) { int status; @@ -528,7 +530,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix) nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); assert(nr_cpus <= MAX_NR_CPUS); - assert(nr_cpus >= 0); + assert((int)nr_cpus >= 0); /* * We dont want to block the signals - that would cause diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0506cd6e04cce..5f5e7df8302d0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -269,7 +269,7 @@ static void print_sym_table(void) } } -static void *display_thread(void *arg) +static void *display_thread(void *arg __used) { struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; int delay_msecs = delay_secs * 1000; @@ -287,7 +287,7 @@ static void *display_thread(void *arg) } /* Tag samples to be skipped. */ -char *skip_symbols[] = { +static const char *skip_symbols[] = { "default_idle", "cpu_idle", "enter_idle", @@ -426,7 +426,7 @@ static void process_event(u64 ip, int counter, int user) struct mmap_data { int counter; void *base; - unsigned int mask; + int mask; unsigned int prev; }; @@ -705,7 +705,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_top(int argc, const char **argv, const char *prefix) +int cmd_top(int argc, const char **argv, const char *prefix __used) { int counter; diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 4eb725933703b..c5656784c61d5 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -229,9 +229,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) use_pager = 1; commit_pager_choice(); - if (p->option & NEED_WORK_TREE) - /* setup_work_tree() */; - status = p->fn(argc, argv, prefix); if (status) return status & 0xff; @@ -266,7 +263,7 @@ static void handle_internal_command(int argc, const char **argv) { "annotate", cmd_annotate, 0 }, { "version", cmd_version, 0 }, }; - int i; + unsigned int i; static const char ext[] = STRIP_EXTENSION; if (sizeof(ext) > 1) { diff --git a/tools/perf/perf.h b/tools/perf/perf.h index ce394192c85a2..27887c916439f 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -52,6 +52,8 @@ static inline unsigned long long rdclock(void) #define __user #define asmlinkage +#define __used __attribute__((__unused__)) + #define unlikely(x) __builtin_expect(!!(x), 0) #define min(x, y) ({ \ typeof(x) _min1 = (x); \ diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index 9b3dd2b428df8..b8144e80bb1e5 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c @@ -3,7 +3,7 @@ static const char *alias_key; static char *alias_val; -static int alias_lookup_cb(const char *k, const char *v, void *cb) +static int alias_lookup_cb(const char *k, const char *v, void *cb __used) { if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { if (!v) diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 393d6146d13b3..161d5f413e287 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -3,6 +3,7 @@ #include "util.h" #include "strbuf.h" +#include "../perf.h" #define PERF_DIR_ENVIRONMENT "PERF_DIR" #define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 440db12c63594..3dceabd9b5efa 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -92,7 +92,7 @@ static void fill_node(struct callchain_node *node, struct ip_callchain *chain, int start, struct symbol **syms) { - int i; + unsigned int i; for (i = start; i < chain->nr; i++) { struct callchain_list *call; @@ -135,7 +135,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, { struct callchain_node *new; struct list_head *old_tail; - int idx_total = idx_parents + idx_local; + unsigned int idx_total = idx_parents + idx_local; /* split */ new = create_child(parent, true); @@ -164,17 +164,18 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start, struct symbol **syms); + unsigned int start, struct symbol **syms); static void __append_chain_children(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms, int start) + struct symbol **syms, unsigned int start) { struct callchain_node *rnode; /* lookup in childrens */ list_for_each_entry(rnode, &root->children, brothers) { - int ret = __append_chain(rnode, chain, start, syms); + unsigned int ret = __append_chain(rnode, chain, start, syms); + if (!ret) return; } @@ -184,10 +185,10 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain, static int __append_chain(struct callchain_node *root, struct ip_callchain *chain, - int start, struct symbol **syms) + unsigned int start, struct symbol **syms) { struct callchain_list *cnode; - int i = start; + unsigned int i = start; bool found = false; /* diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index c942daa712e6f..251d99ecd2255 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -10,15 +10,15 @@ struct callchain_node { struct callchain_node *parent; struct list_head brothers; - struct list_head children; - struct list_head val; + struct list_head children; + struct list_head val; struct rb_node rb_node; - int val_nr; - int hit; + unsigned int val_nr; + u64 hit; }; struct callchain_list { - unsigned long ip; + u64 ip; struct symbol *sym; struct list_head list; }; diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 9a8c20ccc53e2..26f82318b86bb 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -11,7 +11,8 @@ static int parse_color(const char *name, int len) }; char *end; int i; - for (i = 0; i < ARRAY_SIZE(color_names); i++) { + + for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) { const char *str = color_names[i]; if (!strncasecmp(name, str, len) && !str[len]) return i - 1; @@ -28,7 +29,8 @@ static int parse_attr(const char *name, int len) static const char * const attr_names[] = { "bold", "dim", "ul", "blink", "reverse" }; - int i; + unsigned int i; + for (i = 0; i < ARRAY_SIZE(attr_names); i++) { const char *str = attr_names[i]; if (!strncasecmp(name, str, len) && !str[len]) @@ -222,10 +224,12 @@ int color_fwrite_lines(FILE *fp, const char *color, { if (!*color) return fwrite(buf, count, 1, fp) != 1; + while (count) { char *p = memchr(buf, '\n', count); + if (p != buf && (fputs(color, fp) < 0 || - fwrite(buf, p ? p - buf : count, 1, fp) != 1 || + fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || fputs(PERF_COLOR_RESET, fp) < 0)) return -1; if (!p) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 3dd13faa6a27f..780df541006dd 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -47,10 +47,12 @@ static int get_next_char(void) static char *parse_value(void) { static char value[1024]; - int quote = 0, comment = 0, len = 0, space = 0; + int quote = 0, comment = 0, space = 0; + size_t len = 0; for (;;) { int c = get_next_char(); + if (len >= sizeof(value) - 1) return NULL; if (c == '\n') { @@ -353,13 +355,13 @@ int perf_config_string(const char **dest, const char *var, const char *value) return 0; } -static int perf_default_core_config(const char *var, const char *value) +static int perf_default_core_config(const char *var __used, const char *value __used) { /* Add other config variables here and to Documentation/config.txt. */ return 0; } -int perf_default_config(const char *var, const char *value, void *dummy) +int perf_default_config(const char *var, const char *value, void *dummy __used) { if (!prefixcmp(var, "core.")) return perf_default_core_config(var, value); @@ -471,10 +473,10 @@ static int matches(const char* key, const char* value) !regexec(store.value_regex, value, 0, NULL, 0))); } -static int store_aux(const char* key, const char* value, void *cb) +static int store_aux(const char* key, const char* value, void *cb __used) { + int section_len; const char *ep; - size_t section_len; switch (store.state) { case KEY_SEEN: @@ -551,7 +553,7 @@ static int store_write_section(int fd, const char* key) strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); } - success = write_in_full(fd, sb.buf, sb.len) == sb.len; + success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); strbuf_release(&sb); return success; @@ -599,7 +601,7 @@ static int store_write_pair(int fd, const char* key, const char* value) } strbuf_addf(&sb, "%s\n", quote); - success = write_in_full(fd, sb.buf, sb.len) == sb.len; + success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); strbuf_release(&sb); return success; @@ -741,7 +743,7 @@ int perf_config_set_multivar(const char* key, const char* value, } else { struct stat st; char* contents; - size_t contents_sz, copy_begin, copy_end; + ssize_t contents_sz, copy_begin, copy_end; int i, new_line = 0; if (value_regex == NULL) diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c index d392922631530..34a3528673822 100644 --- a/tools/perf/util/exec_cmd.c +++ b/tools/perf/util/exec_cmd.c @@ -1,6 +1,9 @@ #include "cache.h" #include "exec_cmd.h" #include "quote.h" + +#include <string.h> + #define MAX_ARGS 32 extern char **environ; @@ -51,7 +54,7 @@ const char *perf_extract_argv0_path(const char *argv0) slash--; if (slash >= argv0) { - argv0_path = strndup(argv0, slash - argv0); + argv0_path = xstrndup(argv0, slash - argv0); return slash + 1; } diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 17a00e0df2c49..fbb00978b2e29 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -26,7 +26,7 @@ static int term_columns(void) return 80; } -void add_cmdname(struct cmdnames *cmds, const char *name, int len) +void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { struct cmdname *ent = malloc(sizeof(*ent) + len + 1); @@ -40,7 +40,8 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len) static void clean_cmdnames(struct cmdnames *cmds) { - int i; + unsigned int i; + for (i = 0; i < cmds->cnt; ++i) free(cmds->names[i]); free(cmds->names); @@ -57,7 +58,7 @@ static int cmdname_compare(const void *a_, const void *b_) static void uniq(struct cmdnames *cmds) { - int i, j; + unsigned int i, j; if (!cmds->cnt) return; @@ -71,7 +72,7 @@ static void uniq(struct cmdnames *cmds) void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) { - int ci, cj, ei; + size_t ci, cj, ei; int cmp; ci = cj = ei = 0; @@ -106,8 +107,9 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest) printf(" "); for (j = 0; j < cols; j++) { - int n = j * rows + i; - int size = space; + unsigned int n = j * rows + i; + unsigned int size = space; + if (n >= cmds->cnt) break; if (j == cols-1 || n + rows >= cmds->cnt) @@ -208,7 +210,7 @@ void load_command_list(const char *prefix, void list_commands(const char *title, struct cmdnames *main_cmds, struct cmdnames *other_cmds) { - int i, longest = 0; + unsigned int i, longest = 0; for (i = 0; i < main_cmds->cnt; i++) if (longest < main_cmds->names[i]->len) @@ -239,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds, int is_in_cmdlist(struct cmdnames *c, const char *s) { - int i; + unsigned int i; + for (i = 0; i < c->cnt; i++) if (!strcmp(s, c->names[i]->name)) return 1; @@ -271,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2) static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) { - int i; + unsigned int i; + ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); for (i = 0; i < old->cnt; i++) @@ -283,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) const char *help_unknown_cmd(const char *cmd) { - int i, n = 0, best_similarity = 0; + unsigned int i, n = 0, best_similarity = 0; struct cmdnames main_cmds, other_cmds; memset(&main_cmds, 0, sizeof(main_cmds)); @@ -345,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd) exit(1); } -int cmd_version(int argc, const char **argv, const char *prefix) +int cmd_version(int argc __used, const char **argv __used, const char *prefix __used) { printf("perf version %s\n", perf_version_string); return 0; diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h index 56bc15406ffc5..7128783637b4a 100644 --- a/tools/perf/util/help.h +++ b/tools/perf/util/help.h @@ -2,8 +2,8 @@ #define HELP_H struct cmdnames { - int alloc; - int cnt; + size_t alloc; + size_t cnt; struct cmdname { size_t len; /* also used for similarity index in help.c */ char name[FLEX_ARRAY]; @@ -19,7 +19,7 @@ static inline void mput_char(char c, unsigned int num) void load_command_list(const char *prefix, struct cmdnames *main_cmds, struct cmdnames *other_cmds); -void add_cmdname(struct cmdnames *cmds, const char *name, int len); +void add_cmdname(struct cmdnames *cmds, const char *name, size_t len); /* Here we require that excludes is a sorted list. */ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); int is_in_cmdlist(struct cmdnames *c, const char *s); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e6b83a3311a56..aed70901df24b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -385,7 +385,7 @@ static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) return 1; } -int parse_events(const struct option *opt, const char *str, int unset) +int parse_events(const struct option *opt __used, const char *str, int unset __used) { struct perf_counter_attr attr; diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index b3affb1658d2a..9a897b7cce790 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -485,7 +485,7 @@ int parse_options_usage(const char * const *usagestr, } -int parse_opt_verbosity_cb(const struct option *opt, const char *arg, +int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, int unset) { int *target = opt->value; diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index a1039a6ce0eba..15c8aba9c62e7 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -90,21 +90,20 @@ struct option { intptr_t defval; }; -#define OPT_END() { OPTION_END } -#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) } -#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } -#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } -#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } -#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) } -#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } -#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } -#define OPT_LONG(s, l, v, h) { OPTION_LONG, (s), (l), (v), NULL, (h) } -#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_END() { .type = OPTION_END } +#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } +#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } +#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } +#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } +#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } +#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } #define OPT_DATE(s, l, v, h) \ - { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ - parse_opt_approxidate_cb } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ - { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } /* parse_options() will filter out the processed options and leave the * non-option argments in argv[]. diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c index f18c5212bc92b..c6e5dc0dc82f6 100644 --- a/tools/perf/util/quote.c +++ b/tools/perf/util/quote.c @@ -162,12 +162,16 @@ static inline int sq_must_quote(char c) return sq_lookup[(unsigned char)c] + quote_path_fully > 0; } -/* returns the longest prefix not needing a quote up to maxlen if positive. - This stops at the first \0 because it's marked as a character needing an - escape */ -static size_t next_quote_pos(const char *s, ssize_t maxlen) +/* + * Returns the longest prefix not needing a quote up to maxlen if + * positive. + * This stops at the first \0 because it's marked as a character + * needing an escape. + */ +static ssize_t next_quote_pos(const char *s, ssize_t maxlen) { - size_t len; + ssize_t len; + if (maxlen < 0) { for (len = 0; !sq_must_quote(s[len]); len++); } else { @@ -192,22 +196,22 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen) static size_t quote_c_style_counted(const char *name, ssize_t maxlen, struct strbuf *sb, FILE *fp, int no_dq) { -#undef EMIT -#define EMIT(c) \ - do { \ - if (sb) strbuf_addch(sb, (c)); \ - if (fp) fputc((c), fp); \ - count++; \ +#define EMIT(c) \ + do { \ + if (sb) strbuf_addch(sb, (c)); \ + if (fp) fputc((c), fp); \ + count++; \ } while (0) -#define EMITBUF(s, l) \ - do { \ - int __ret; \ - if (sb) strbuf_add(sb, (s), (l)); \ - if (fp) __ret = fwrite((s), (l), 1, fp); \ - count += (l); \ + +#define EMITBUF(s, l) \ + do { \ + int __ret; \ + if (sb) strbuf_add(sb, (s), (l)); \ + if (fp) __ret = fwrite((s), (l), 1, fp); \ + count += (l); \ } while (0) - size_t len, count = 0; + ssize_t len, count = 0; const char *p = name; for (;;) { @@ -273,8 +277,8 @@ void write_name_quoted(const char *name, FILE *fp, int terminator) fputc(terminator, fp); } -extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, - const char *name, FILE *fp, int terminator) +void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, + const char *name, FILE *fp, int terminator) { int needquote = 0; @@ -306,7 +310,7 @@ char *quote_path_relative(const char *in, int len, len = strlen(in); /* "../" prefix itself does not need quoting, but "in" might. */ - needquote = next_quote_pos(in, len) < len; + needquote = (next_quote_pos(in, len) < len); strbuf_setlen(out, 0); strbuf_grow(out, len); diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index 5dfad89816db1..a5454a1d1c137 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h @@ -53,7 +53,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); extern void write_name_quoted(const char *name, FILE *, int terminator); -extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, +extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, const char *name, FILE *, int terminator); /* quote path as relative to the given prefix */ diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 464e7ca898cfe..5249d5a1b0c20 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -16,7 +16,7 @@ int prefixcmp(const char *str, const char *prefix) */ char strbuf_slopbuf[1]; -void strbuf_init(struct strbuf *sb, size_t hint) +void strbuf_init(struct strbuf *sb, ssize_t hint) { sb->alloc = sb->len = 0; sb->buf = strbuf_slopbuf; @@ -92,7 +92,8 @@ void strbuf_ltrim(struct strbuf *sb) void strbuf_tolower(struct strbuf *sb) { - int i; + unsigned int i; + for (i = 0; i < sb->len; i++) sb->buf[i] = tolower(sb->buf[i]); } @@ -264,7 +265,7 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) return res; } -ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) +ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) { size_t oldlen = sb->len; size_t oldalloc = sb->alloc; @@ -293,7 +294,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) #define STRBUF_MAXLINK (2*PATH_MAX) -int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) +int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint) { size_t oldalloc = sb->alloc; @@ -301,7 +302,7 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) hint = 32; while (hint < STRBUF_MAXLINK) { - int len; + ssize_t len; strbuf_grow(sb, hint); len = readlink(path, sb->buf, hint); @@ -343,7 +344,7 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term) return 0; } -int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) +int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint) { int fd, len; diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 9ee908a3ec5d4..d2aa86c014c1b 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h @@ -50,7 +50,7 @@ struct strbuf { #define STRBUF_INIT { 0, 0, strbuf_slopbuf } /*----- strbuf life cycle -----*/ -extern void strbuf_init(struct strbuf *, size_t); +extern void strbuf_init(struct strbuf *buf, ssize_t hint); extern void strbuf_release(struct strbuf *); extern char *strbuf_detach(struct strbuf *, size_t *); extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); @@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { } /*----- strbuf size related -----*/ -static inline size_t strbuf_avail(const struct strbuf *sb) { +static inline ssize_t strbuf_avail(const struct strbuf *sb) { return sb->alloc ? sb->alloc - sb->len - 1 : 0; } @@ -122,9 +122,9 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); /* XXX: if read fails, any partial read is undone */ -extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); -extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint); -extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint); +extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); +extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint); +extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint); extern int strbuf_getline(struct strbuf *, FILE *, int); diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c index 6350d65f6d9e5..4574ac28396f6 100644 --- a/tools/perf/util/wrapper.c +++ b/tools/perf/util/wrapper.c @@ -7,7 +7,7 @@ * There's no pack memory to release - but stay close to the Git * version so wrap this away: */ -static inline void release_pack_memory(size_t size, int flag) +static inline void release_pack_memory(size_t size __used, int flag __used) { } @@ -59,7 +59,8 @@ void *xmemdupz(const void *data, size_t len) char *xstrndup(const char *str, size_t len) { char *p = memchr(str, '\0', len); - return xmemdupz(str, p ? p - str : len); + + return xmemdupz(str, p ? (size_t)(p - str) : len); } void *xrealloc(void *ptr, size_t size) -- GitLab From b9ebdcc0ce1c676ebf5dc4f6df6b440d8fcf88ab Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 1 Jul 2009 15:05:09 +0530 Subject: [PATCH 0500/1002] perf stat: Define MATCH_EVENT for easy attr checking MATCH_EVENT is useful: 1. for multiple attrs checking 2. avoid repetition of PERF_TYPE_ and PERF_COUNT_ and save space 3. avoids line breakage Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <1246440909.3403.5.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 095a90e012a17..01cc07efb728a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -96,6 +96,10 @@ static u64 walltime_nsecs_noise; static u64 runtime_cycles_avg; static u64 runtime_cycles_noise; +#define MATCH_EVENT(t, c, counter) \ + (attrs[counter].type == PERF_TYPE_##t && \ + attrs[counter].config == PERF_COUNT_##c) + #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" @@ -133,13 +137,8 @@ static void create_perf_stat_counter(int counter, int pid) */ static inline int nsec_counter(int counter) { - if (attrs[counter].type != PERF_TYPE_SOFTWARE) - return 0; - - if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK) - return 1; - - if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) + if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || + MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) return 1; return 0; @@ -194,11 +193,9 @@ static void read_counter(int counter) /* * Save the full runtime - to allow normalization during printout: */ - if (attrs[counter].type == PERF_TYPE_SOFTWARE && - attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) + if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) runtime_nsecs[run_idx] = count[0]; - if (attrs[counter].type == PERF_TYPE_HARDWARE && - attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) + if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) runtime_cycles[run_idx] = count[0]; } @@ -292,9 +289,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise) fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); - if (attrs[counter].type == PERF_TYPE_SOFTWARE && - attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { - + if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { if (walltime_nsecs_avg) fprintf(stderr, " # %10.3f CPUs ", (double)count[0] / (double)walltime_nsecs_avg); @@ -307,9 +302,7 @@ static void abs_printout(int counter, u64 *count, u64 *noise) fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); if (runtime_cycles_avg && - attrs[counter].type == PERF_TYPE_HARDWARE && - attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { - + MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { fprintf(stderr, " # %10.3f IPC ", (double)count[0] / (double)runtime_cycles_avg); } else { -- GitLab From 44973998a111dfda09b952aa0f27cad326a97793 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 1 Jul 2009 17:49:38 +0530 Subject: [PATCH 0501/1002] x86: Remove double declaration of MSR_P6_EVNTSEL0 and MSR_P6_EVNTSEL1 MSR_P6_EVNTSEL0 and MSR_P6_EVNTSEL1 is already declared in msr-index.h. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> LKML-Reference: <1246450778.6940.8.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/msr-index.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1692fb5050e35..6be7fc254b599 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -246,10 +246,6 @@ #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) -/* Intel Model 6 */ -#define MSR_P6_EVNTSEL0 0x00000186 -#define MSR_P6_EVNTSEL1 0x00000187 - /* P4/Xeon+ specific */ #define MSR_IA32_MCG_EAX 0x00000180 #define MSR_IA32_MCG_EBX 0x00000181 -- GitLab From 73c24cb86c51ff6445b292d9914d31236204393b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 1 Jul 2009 18:36:18 +0530 Subject: [PATCH 0502/1002] perf list: Add cache events After: $ ./perf list List of pre-defined events (to be used in -e): cpu-cycles OR cycles [Hardware event] instructions [Hardware event] cache-references [Hardware event] cache-misses [Hardware event] branch-instructions OR branches [Hardware event] branch-misses [Hardware event] bus-cycles [Hardware event] cpu-clock [Software event] task-clock [Software event] page-faults OR faults [Software event] minor-faults [Software event] major-faults [Software event] context-switches OR cs [Software event] cpu-migrations OR migrations [Software event] L1-d$-loads [Hardware cache event] L1-d$-load-misses [Hardware cache event] L1-d$-stores [Hardware cache event] L1-d$-store-misses [Hardware cache event] L1-d$-prefetches [Hardware cache event] L1-d$-prefetch-misses [Hardware cache event] L1-i$-loads [Hardware cache event] L1-i$-load-misses [Hardware cache event] L1-i$-prefetches [Hardware cache event] L1-i$-prefetch-misses [Hardware cache event] LLC-loads [Hardware cache event] LLC-load-misses [Hardware cache event] LLC-stores [Hardware cache event] LLC-store-misses [Hardware cache event] LLC-prefetches [Hardware cache event] LLC-prefetch-misses [Hardware cache event] dTLB-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-stores [Hardware cache event] dTLB-store-misses [Hardware cache event] dTLB-prefetches [Hardware cache event] dTLB-prefetch-misses [Hardware cache event] iTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] branch-loads [Hardware cache event] branch-load-misses [Hardware cache event] rNNN [raw hardware event descriptor] Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <1246453578.3072.1.camel@ht.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-events.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index aed70901df24b..5184959e0615b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -428,7 +428,7 @@ static const char * const event_type_descriptors[] = { void print_events(void) { struct event_symbol *syms = event_symbols; - unsigned int i, type, prev_type = -1; + unsigned int i, type, op, prev_type = -1; char name[40]; fprintf(stderr, "\n"); @@ -452,6 +452,21 @@ void print_events(void) prev_type = type; } + fprintf(stderr, "\n"); + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + fprintf(stderr, " %-40s [%s]\n", + event_cache_name(type, op, i), + event_type_descriptors[4]); + } + } + } + fprintf(stderr, "\n"); fprintf(stderr, " %-40s [raw hardware event descriptor]\n", "rNNN"); -- GitLab From b25ae679f613ed04aaf6ccbfdb9122fce668e4bb Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 1 Jul 2009 19:53:14 +0530 Subject: [PATCH 0503/1002] x86: Mark device_nb as static and fix NULL noise This sparse warning: arch/x86/kernel/amd_iommu.c:1195:23: warning: symbol 'device_nb' was not declared. Should it be static? triggers because device_nb is global but is only used in a single .c file. change device_nb to static to fix that - this also addresses the sparse warning. This sparse warning: arch/x86/kernel/amd_iommu.c:1766:10: warning: Using plain integer as NULL pointer triggers because plain integer 0 is used in place of a NULL pointer. change 0 to NULL to fix that - this also address the sparse warning. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Joerg Roedel <joerg.roedel@amd.com> LKML-Reference: <1246458194.6940.20.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/amd_iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 9372f0406ad4a..6c99f50378013 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1192,7 +1192,7 @@ static int device_change_notifier(struct notifier_block *nb, return 0; } -struct notifier_block device_nb = { +static struct notifier_block device_nb = { .notifier_call = device_change_notifier, }; @@ -1763,7 +1763,7 @@ static void *alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; virt_addr = (void *)__get_free_pages(flag, get_order(size)); if (!virt_addr) - return 0; + return NULL; paddr = virt_to_phys(virt_addr); -- GitLab From 76c06927f2a78143763dcff9b4c362d15eb29cc2 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 1 Jul 2009 19:54:23 +0530 Subject: [PATCH 0504/1002] x86: Declare check_efer() before it gets used This sparse warning: arch/x86/mm/init.c:83:16: warning: symbol 'check_efer' was not declared. Should it be static? triggers because check_efer() is not decalared before using it. asm/proto.h includes the declaration of check_efer(), so including asm/proto.h to fix that - this also addresses the sparse warning. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <1246458263.6940.22.camel@hpdv5.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/mm/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 47ce9a2ce5e7c..0607119cef94f 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -12,6 +12,7 @@ #include <asm/system.h> #include <asm/tlbflush.h> #include <asm/tlb.h> +#include <asm/proto.h> DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -- GitLab From ff84847171508a3c76eb7e483204d1be7738729b Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 1 Jul 2009 18:08:01 +0200 Subject: [PATCH 0505/1002] ALSA: hda - Add quirk for HP 6930p Added a quirk model=laptop for HP 6930p (103c:30dc) with AD1984A codec. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_analog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 84cc49ca91487..85e8618e8497d 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3966,6 +3966,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), + SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), -- GitLab From 57d81f6f393b245894ca0cd828f80ce7e3294f39 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Wed, 1 Jul 2009 09:43:53 +0200 Subject: [PATCH 0506/1002] kmemleak: Fix scheduling-while-atomic bug One of the kmemleak changes caused the following scheduling-while-holding-the-tasklist-lock regression on x86: BUG: sleeping function called from invalid context at mm/kmemleak.c:795 in_atomic(): 1, irqs_disabled(): 0, pid: 1737, name: kmemleak 2 locks held by kmemleak/1737: #0: (scan_mutex){......}, at: [<c10c4376>] kmemleak_scan_thread+0x45/0x86 #1: (tasklist_lock){......}, at: [<c10c3bb4>] kmemleak_scan+0x1a9/0x39c Pid: 1737, comm: kmemleak Not tainted 2.6.31-rc1-tip #59266 Call Trace: [<c105ac0f>] ? __debug_show_held_locks+0x1e/0x20 [<c102e490>] __might_sleep+0x10a/0x111 [<c10c38d5>] scan_yield+0x17/0x3b [<c10c3970>] scan_block+0x39/0xd4 [<c10c3bc6>] kmemleak_scan+0x1bb/0x39c [<c10c4331>] ? kmemleak_scan_thread+0x0/0x86 [<c10c437b>] kmemleak_scan_thread+0x4a/0x86 [<c104d73e>] kthread+0x6e/0x73 [<c104d6d0>] ? kthread+0x0/0x73 [<c100959f>] kernel_thread_helper+0x7/0x10 kmemleak: 834 new suspected memory leaks (see /sys/kernel/debug/kmemleak) The bit causing it is highly dubious: static void scan_yield(void) { might_sleep(); if (time_is_before_eq_jiffies(next_scan_yield)) { schedule(); next_scan_yield = jiffies + jiffies_scan_yield; } } It called deep inside the codepath and in a conditional way, and that is what crapped up when one of the new scan_block() uses grew a tasklist_lock dependency. This minimal patch removes that yielding stuff and adds the proper cond_resched(). The background scanning thread could probably also be reniced to +10. Signed-off-by: Ingo Molnar <mingo@elte.hu> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/kmemleak.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index eeece2deace26..e766e1da09d28 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -105,7 +105,6 @@ #define MAX_TRACE 16 /* stack trace length */ #define REPORTS_NR 50 /* maximum number of reported leaks */ #define MSECS_MIN_AGE 5000 /* minimum object age for reporting */ -#define MSECS_SCAN_YIELD 10 /* CPU yielding period */ #define SECS_FIRST_SCAN 60 /* delay before the first scan */ #define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */ @@ -186,10 +185,7 @@ static atomic_t kmemleak_error = ATOMIC_INIT(0); static unsigned long min_addr = ULONG_MAX; static unsigned long max_addr; -/* used for yielding the CPU to other tasks during scanning */ -static unsigned long next_scan_yield; static struct task_struct *scan_thread; -static unsigned long jiffies_scan_yield; /* used to avoid reporting of recently allocated objects */ static unsigned long jiffies_min_age; static unsigned long jiffies_last_scan; @@ -785,21 +781,6 @@ void kmemleak_no_scan(const void *ptr) } EXPORT_SYMBOL(kmemleak_no_scan); -/* - * Yield the CPU so that other tasks get a chance to run. The yielding is - * rate-limited to avoid excessive number of calls to the schedule() function - * during memory scanning. - */ -static void scan_yield(void) -{ - might_sleep(); - - if (time_is_before_eq_jiffies(next_scan_yield)) { - schedule(); - next_scan_yield = jiffies + jiffies_scan_yield; - } -} - /* * Memory scanning is a long process and it needs to be interruptable. This * function checks whether such interrupt condition occured. @@ -840,15 +821,6 @@ static void scan_block(void *_start, void *_end, if (scan_should_stop()) break; - /* - * When scanning a memory block with a corresponding - * kmemleak_object, the CPU yielding is handled in the calling - * code since it holds the object->lock to avoid the block - * freeing. - */ - if (!scanned) - scan_yield(); - object = find_and_get_object(pointer, 1); if (!object) continue; @@ -1014,7 +986,7 @@ static void kmemleak_scan(void) */ object = list_entry(gray_list.next, typeof(*object), gray_list); while (&object->gray_list != &gray_list) { - scan_yield(); + cond_resched(); /* may add new objects to the list */ if (!scan_should_stop()) @@ -1385,7 +1357,6 @@ void __init kmemleak_init(void) int i; unsigned long flags; - jiffies_scan_yield = msecs_to_jiffies(MSECS_SCAN_YIELD); jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE); jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000); -- GitLab From da9ff1f796e81976935407251815838bef9868d4 Mon Sep 17 00:00:00 2001 From: Mark Brown <broonie@opensource.wolfsonmicro.com> Date: Wed, 1 Jul 2009 18:23:26 +0100 Subject: [PATCH 0507/1002] ASoC: Only disable pxa2xx-i2s clocks if we enabled them The clock API can't cope with unbalanced enables and disables and we only enable in hw_params() but try to disable in shutdown. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/pxa/pxa2xx-i2s.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 4743e262895d9..6b8f655d1ad82 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -167,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, BUG_ON(IS_ERR(clk_i2s)); clk_enable(clk_i2s); + dai->private_data = dai; pxa_i2s_wait(); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -255,7 +256,10 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { SACR0 &= ~SACR0_ENB; pxa_i2s_wait(); - clk_disable(clk_i2s); + if (dai->private_data != NULL) { + clk_disable(clk_i2s); + dai->private_data = NULL; + } } } @@ -336,6 +340,7 @@ static int pxa2xx_i2s_probe(struct platform_device *dev) return PTR_ERR(clk_i2s); pxa_i2s_dai.dev = &dev->dev; + pxa_i2s_dai.private_data = NULL; ret = snd_soc_register_dai(&pxa_i2s_dai); if (ret != 0) clk_put(clk_i2s); -- GitLab From 63eeaf38251183ec2b1caee11e4a2c040cb5ce6c Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Thu, 18 Jun 2009 16:56:52 -0700 Subject: [PATCH 0508/1002] drm/i915: enable error detection & state collection This patch enables error detection by enabling several types of error interrupts. When an error interrupt is received, the interrupt handler captures the error state; hopefully resulting in an accurate set of error data (error type, active head pointer, etc.). The new record is then available from sysfs. The current code will also dump the error state to the system log. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 19 ++++ drivers/gpu/drm/i915/i915_gem_debugfs.c | 34 ++++++ drivers/gpu/drm/i915/i915_irq.c | 139 +++++++++++++++++++++++- drivers/gpu/drm/i915/i915_reg.h | 14 +++ 5 files changed, 204 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f112c769d5334..f83364974a8a7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1180,6 +1180,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) pci_enable_msi(dev->pdev); spin_lock_init(&dev_priv->user_irq_lock); + spin_lock_init(&dev_priv->error_lock); dev_priv->user_irq_refcount = 0; ret = drm_vblank_init(dev, I915_NUM_PIPE); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bb4c2d387b6c3..596e119d3e0e3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -133,6 +133,22 @@ struct sdvo_device_mapping { u8 initialized; }; +struct drm_i915_error_state { + u32 eir; + u32 pgtbl_er; + u32 pipeastat; + u32 pipebstat; + u32 ipeir; + u32 ipehr; + u32 instdone; + u32 acthd; + u32 instpm; + u32 instps; + u32 instdone1; + u32 seqno; + struct timeval time; +}; + typedef struct drm_i915_private { struct drm_device *dev; @@ -209,6 +225,9 @@ typedef struct drm_i915_private { int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */ + spinlock_t error_lock; + struct drm_i915_error_state *first_error; + /* Register state */ u8 saveLBB; u32 saveDSPACNTR; diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index 28146e405e874..cacae945338b8 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -323,6 +323,39 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) return 0; } +static int i915_error_state(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_error_state *error; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->error_lock, flags); + if (!dev_priv->first_error) { + seq_printf(m, "no error state collected\n"); + goto out; + } + + error = dev_priv->first_error; + + seq_printf(m, "EIR: 0x%08x\n", error->eir); + seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er); + seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); + seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir); + seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); + seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); + seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); + if (IS_I965G(dev)) { + seq_printf(m, " INSTPS: 0x%08x\n", error->instps); + seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); + } + +out: + spin_unlock_irqrestore(&dev_priv->error_lock, flags); + + return 0; +} static struct drm_info_list i915_gem_debugfs_list[] = { {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, @@ -336,6 +369,7 @@ static struct drm_info_list i915_gem_debugfs_list[] = { {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, {"i915_batchbuffers", i915_batchbuffer_info, 0}, + {"i915_error_state", i915_error_state, 0}, }; #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 228546f6eaa4f..17b308592c4fc 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -26,6 +26,7 @@ * */ +#include <linux/sysrq.h> #include "drmP.h" #include "drm.h" #include "i915_drm.h" @@ -41,9 +42,10 @@ * we leave them always unmasked in IMR and then control enabling them through * PIPESTAT alone. */ -#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) +#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \ + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) /** Interrupts that we mask and unmask at runtime. */ #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) @@ -288,6 +290,47 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) return ret; } +static void i915_capture_error_state(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_error_state *error; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->error_lock, flags); + if (dev_priv->first_error) + goto out; + + error = kmalloc(sizeof(*error), GFP_ATOMIC); + if (!error) { + DRM_DEBUG("out ot memory, not capturing error state\n"); + goto out; + } + + error->eir = I915_READ(EIR); + error->pgtbl_er = I915_READ(PGTBL_ER); + error->pipeastat = I915_READ(PIPEASTAT); + error->pipebstat = I915_READ(PIPEBSTAT); + error->instpm = I915_READ(INSTPM); + if (!IS_I965G(dev)) { + error->ipeir = I915_READ(IPEIR); + error->ipehr = I915_READ(IPEHR); + error->instdone = I915_READ(INSTDONE); + error->acthd = I915_READ(ACTHD); + } else { + error->ipeir = I915_READ(IPEIR_I965); + error->ipehr = I915_READ(IPEHR_I965); + error->instdone = I915_READ(INSTDONE_I965); + error->instps = I915_READ(INSTPS); + error->instdone1 = I915_READ(INSTDONE1); + error->acthd = I915_READ(ACTHD_I965); + } + + dev_priv->first_error = error; + +out: + spin_unlock_irqrestore(&dev_priv->error_lock, flags); +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -362,6 +405,80 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_READ(PORT_HOTPLUG_STAT); } + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) { + u32 eir = I915_READ(EIR); + + i915_capture_error_state(dev); + + printk(KERN_ERR "render error detected, EIR: 0x%08x\n", + eir); + if (eir & I915_ERROR_PAGE_TABLE) { + u32 pgtbl_err = I915_READ(PGTBL_ER); + printk(KERN_ERR "page table error\n"); + printk(KERN_ERR " PGTBL_ER: 0x%08x\n", + pgtbl_err); + I915_WRITE(PGTBL_ER, pgtbl_err); + (void)I915_READ(PGTBL_ER); + } + if (eir & I915_ERROR_MEMORY_REFRESH) { + printk(KERN_ERR "memory refresh error\n"); + printk(KERN_ERR "PIPEASTAT: 0x%08x\n", + pipea_stats); + printk(KERN_ERR "PIPEBSTAT: 0x%08x\n", + pipeb_stats); + /* pipestat has already been acked */ + } + if (eir & I915_ERROR_INSTRUCTION) { + printk(KERN_ERR "instruction error\n"); + printk(KERN_ERR " INSTPM: 0x%08x\n", + I915_READ(INSTPM)); + if (!IS_I965G(dev)) { + u32 ipeir = I915_READ(IPEIR); + + printk(KERN_ERR " IPEIR: 0x%08x\n", + I915_READ(IPEIR)); + printk(KERN_ERR " IPEHR: 0x%08x\n", + I915_READ(IPEHR)); + printk(KERN_ERR " INSTDONE: 0x%08x\n", + I915_READ(INSTDONE)); + printk(KERN_ERR " ACTHD: 0x%08x\n", + I915_READ(ACTHD)); + I915_WRITE(IPEIR, ipeir); + (void)I915_READ(IPEIR); + } else { + u32 ipeir = I915_READ(IPEIR_I965); + + printk(KERN_ERR " IPEIR: 0x%08x\n", + I915_READ(IPEIR_I965)); + printk(KERN_ERR " IPEHR: 0x%08x\n", + I915_READ(IPEHR_I965)); + printk(KERN_ERR " INSTDONE: 0x%08x\n", + I915_READ(INSTDONE_I965)); + printk(KERN_ERR " INSTPS: 0x%08x\n", + I915_READ(INSTPS)); + printk(KERN_ERR " INSTDONE1: 0x%08x\n", + I915_READ(INSTDONE1)); + printk(KERN_ERR " ACTHD: 0x%08x\n", + I915_READ(ACTHD_I965)); + I915_WRITE(IPEIR_I965, ipeir); + (void)I915_READ(IPEIR_I965); + } + } + + I915_WRITE(EIR, eir); + (void)I915_READ(EIR); + eir = I915_READ(EIR); + if (eir) { + /* + * some errors might have become stuck, + * mask them. + */ + DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir); + I915_WRITE(EMR, I915_READ(EMR) | eir); + I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); + } + } + I915_WRITE(IIR, iir); new_iir = I915_READ(IIR); /* Flush posted writes */ @@ -732,6 +849,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; + u32 error_mask; DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); @@ -768,6 +886,21 @@ int i915_driver_irq_postinstall(struct drm_device *dev) i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); } + /* + * Enable some error detection, note the instruction error mask + * bit is reserved, so we leave it masked. + */ + if (IS_G4X(dev)) { + error_mask = ~(GM45_ERROR_PAGE_TABLE | + GM45_ERROR_MEM_PRIV | + GM45_ERROR_CP_PRIV | + I915_ERROR_MEMORY_REFRESH); + } else { + error_mask = ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH); + } + I915_WRITE(EMR, error_mask); + /* Disable pipe interrupt enables, clear pending pipe status */ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 88bf7521405f5..ad3d1b5db95ed 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -206,6 +206,7 @@ /* * Instruction and interrupt control regs */ +#define PGTBL_ER 0x02024 #define PRB0_TAIL 0x02030 #define PRB0_HEAD 0x02034 #define PRB0_START 0x02038 @@ -226,11 +227,18 @@ #define PRB1_HEAD 0x02044 /* 915+ only */ #define PRB1_START 0x02048 /* 915+ only */ #define PRB1_CTL 0x0204c /* 915+ only */ +#define IPEIR_I965 0x02064 +#define IPEHR_I965 0x02068 +#define INSTDONE_I965 0x0206c +#define INSTPS 0x02070 /* 965+ only */ +#define INSTDONE1 0x0207c /* 965+ only */ #define ACTHD_I965 0x02074 #define HWS_PGA 0x02080 #define HWS_ADDRESS_MASK 0xfffff000 #define HWS_START_ADDRESS_SHIFT 4 #define IPEIR 0x02088 +#define IPEHR 0x0208c +#define INSTDONE 0x02090 #define NOPID 0x02094 #define HWSTAM 0x02098 #define SCPD0 0x0209c /* 915+ only */ @@ -258,6 +266,12 @@ #define EIR 0x020b0 #define EMR 0x020b4 #define ESR 0x020b8 +#define GM45_ERROR_PAGE_TABLE (1<<5) +#define GM45_ERROR_MEM_PRIV (1<<4) +#define I915_ERROR_PAGE_TABLE (1<<4) +#define GM45_ERROR_CP_PRIV (1<<3) +#define I915_ERROR_MEMORY_REFRESH (1<<1) +#define I915_ERROR_INSTRUCTION (1<<0) #define INSTPM 0x020c0 #define ACTHD 0x020c8 #define FW_BLC 0x020d8 -- GitLab From 3238c0c4d68d9a9022b411a11a4b933fbdb53a14 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 1 Jul 2009 18:56:16 +0100 Subject: [PATCH 0509/1002] intel-iommu: Make iommu=pt work on i386 too Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- arch/x86/kernel/pci-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 47630479b0677..1a041bcf506bd 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -211,11 +211,11 @@ static __init int iommu_setup(char *p) #ifdef CONFIG_SWIOTLB if (!strncmp(p, "soft", 4)) swiotlb = 1; +#endif if (!strncmp(p, "pt", 2)) { iommu_pass_through = 1; return 1; } -#endif gart_parse_options(p); -- GitLab From e2dbe12557d85d81f4527879499f55681c3cca4f Mon Sep 17 00:00:00 2001 From: Amerigo Wang <amwang@redhat.com> Date: Wed, 1 Jul 2009 01:06:26 -0400 Subject: [PATCH 0510/1002] elf: fix one check-after-use Check before use it. Signed-off-by: WANG Cong <amwang@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: David Howells <dhowells@redhat.com> Acked-by: Roland McGrath <roland@redhat.com> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/binfmt_elf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index f1867900e4594..b7c1603cd4bd4 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1522,11 +1522,11 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, info->thread = NULL; psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); - fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); - if (psinfo == NULL) return 0; + fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); + /* * Figure out how many notes we're going to need for each thread. */ -- GitLab From 7662c8bd6545c12ac7b2b39e4554c3ba34789c50 Mon Sep 17 00:00:00 2001 From: Shaohua Li <shaohua.li@intel.com> Date: Fri, 26 Jun 2009 11:23:55 +0800 Subject: [PATCH 0511/1002] drm/i915: add FIFO watermark support This patch from jbarnes and myself adds FIFO watermark control to the driver. This is needed for both power saving features on new platforms with the so-called "big FIFO" and for controlling FIFO allocation between pipes in multi-head configurations. It's also necessary infrastructure to support things like framebuffer compression and configuration supportability checks (i.e. checking a configuration against available bandwidth). Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_dma.c | 40 +++ drivers/gpu/drm/i915/i915_drv.h | 4 + drivers/gpu/drm/i915/i915_irq.c | 4 + drivers/gpu/drm/i915/i915_reg.h | 46 ++- drivers/gpu/drm/i915/intel_display.c | 425 ++++++++++++++++++++++++++- 5 files changed, 513 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index f83364974a8a7..6096600aff607 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1082,6 +1082,44 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) master->driver_priv = NULL; } +static void i915_get_mem_freq(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 tmp; + + if (!IS_IGD(dev)) + return; + + tmp = I915_READ(CLKCFG); + + switch (tmp & CLKCFG_FSB_MASK) { + case CLKCFG_FSB_533: + dev_priv->fsb_freq = 533; /* 133*4 */ + break; + case CLKCFG_FSB_800: + dev_priv->fsb_freq = 800; /* 200*4 */ + break; + case CLKCFG_FSB_667: + dev_priv->fsb_freq = 667; /* 167*4 */ + break; + case CLKCFG_FSB_400: + dev_priv->fsb_freq = 400; /* 100*4 */ + break; + } + + switch (tmp & CLKCFG_MEM_MASK) { + case CLKCFG_MEM_533: + dev_priv->mem_freq = 533; + break; + case CLKCFG_MEM_667: + dev_priv->mem_freq = 667; + break; + case CLKCFG_MEM_800: + dev_priv->mem_freq = 800; + break; + } +} + /** * i915_driver_load - setup chip and create an initial config * @dev: DRM device @@ -1165,6 +1203,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_iomapfree; } + i915_get_mem_freq(dev); + /* On the 945G/GM, the chipset reports the MSI capability on the * integrated graphics even though the support isn't actually there * according to the published specs. It doesn't appear to function diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 596e119d3e0e3..47ecb617e519b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -225,6 +225,8 @@ typedef struct drm_i915_private { int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */ + unsigned int fsb_freq, mem_freq; + spinlock_t error_lock; struct drm_i915_error_state *first_error; @@ -889,6 +891,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) +/* dsparb controlled by hw only */ +#define DSPARB_HWCONTROL(dev) (IS_G4X(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 17b308592c4fc..7ba23a69a0c0e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -376,11 +376,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) * Clear the PIPE(A|B)STAT regs before the IIR */ if (pipea_stats & 0x8000ffff) { + if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) + DRM_DEBUG("pipe a underrun\n"); I915_WRITE(PIPEASTAT, pipea_stats); irq_received = 1; } if (pipeb_stats & 0x8000ffff) { + if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) + DRM_DEBUG("pipe b underrun\n"); I915_WRITE(PIPEBSTAT, pipeb_stats); irq_received = 1; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ad3d1b5db95ed..6c08584840944 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -275,7 +275,13 @@ #define INSTPM 0x020c0 #define ACTHD 0x020c8 #define FW_BLC 0x020d8 +#define FW_BLC2 0x020dc #define FW_BLC_SELF 0x020e0 /* 915+ only */ +#define FW_BLC_SELF_EN (1<<15) +#define MM_BURST_LENGTH 0x00700000 +#define MM_FIFO_WATERMARK 0x0001F000 +#define LM_BURST_LENGTH 0x00000700 +#define LM_FIFO_WATERMARK 0x0000001F #define MI_ARB_STATE 0x020e4 /* 915+ only */ #define CACHE_MODE_0 0x02120 /* 915+ only */ #define CM0_MASK_SHIFT 16 @@ -585,17 +591,21 @@ /* Clocking configuration register */ #define CLKCFG 0x10c00 -#define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ +#define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ -/* this is a guess, could be 5 as well */ +/* Note, below two are guess */ #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ -#define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ #define CLKCFG_FSB_MASK (7 << 0) - +#define CLKCFG_MEM_533 (1 << 4) +#define CLKCFG_MEM_667 (2 << 4) +#define CLKCFG_MEM_800 (3 << 4) +#define CLKCFG_MEM_MASK (7 << 4) + /** GM965 GM45 render standby register */ #define MCHBAR_RENDER_STANDBY 0x111B8 @@ -1595,6 +1605,34 @@ #define DSPARB_CSTART_SHIFT 7 #define DSPARB_BSTART_MASK (0x7f) #define DSPARB_BSTART_SHIFT 0 +#define DSPARB_BEND_SHIFT 9 /* on 855 */ +#define DSPARB_AEND_SHIFT 0 + +#define DSPFW1 0x70034 +#define DSPFW2 0x70038 +#define DSPFW3 0x7003c +#define IGD_SELF_REFRESH_EN (1<<30) + +/* FIFO watermark sizes etc */ +#define I915_FIFO_LINE_SIZE 64 +#define I830_FIFO_LINE_SIZE 32 +#define I945_FIFO_SIZE 127 /* 945 & 965 */ +#define I915_FIFO_SIZE 95 +#define I855GM_FIFO_SIZE 255 +#define I830_FIFO_SIZE 95 +#define I915_MAX_WM 0x3f + +#define IGD_DISPLAY_FIFO 512 /* in 64byte unit */ +#define IGD_FIFO_LINE_SIZE 64 +#define IGD_MAX_WM 0x1ff +#define IGD_DFT_WM 0x3f +#define IGD_DFT_HPLLOFF_WM 0 +#define IGD_GUARD_WM 10 +#define IGD_CURSOR_FIFO 64 +#define IGD_CURSOR_MAX_WM 0x3f +#define IGD_CURSOR_DFT_WM 0 +#define IGD_CURSOR_GUARD_WM 5 + /* * The two pipe frame counter registers are not synchronized, so * reading a stable value is somewhat tricky. The following code diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 73e7b9cecac82..a84ac05ef0483 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -25,6 +25,7 @@ */ #include <linux/i2c.h> +#include <linux/kernel.h> #include "drmP.h" #include "intel_drv.h" #include "i915_drm.h" @@ -34,6 +35,7 @@ #include "drm_crtc_helper.h" bool intel_pipe_has_type (struct drm_crtc *crtc, int type); +static void intel_update_watermarks(struct drm_device *dev); typedef struct { /* given values */ @@ -1005,7 +1007,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - int plane = intel_crtc->pipe; + int plane = intel_crtc->plane; int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; @@ -1335,8 +1337,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) /* Give the overlay scaler a chance to enable if it's on this pipe */ //intel_crtc_dpms_video(crtc, true); TODO + intel_update_watermarks(dev); break; case DRM_MODE_DPMS_OFF: + intel_update_watermarks(dev); /* Give the overlay scaler a chance to disable if it's on this pipe */ //intel_crtc_dpms_video(crtc, FALSE); TODO @@ -1515,7 +1519,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev) return 0; /* Silence gcc warning */ } - /** * Return the pipe currently connected to the panel fitter, * or -1 if the panel fitter is not present or not in use @@ -1585,6 +1588,420 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, } +struct intel_watermark_params { + unsigned long fifo_size; + unsigned long max_wm; + unsigned long default_wm; + unsigned long guard_size; + unsigned long cacheline_size; +}; + +/* IGD has different values for various configs */ +static struct intel_watermark_params igd_display_wm = { + IGD_DISPLAY_FIFO, + IGD_MAX_WM, + IGD_DFT_WM, + IGD_GUARD_WM, + IGD_FIFO_LINE_SIZE +}; +static struct intel_watermark_params igd_display_hplloff_wm = { + IGD_DISPLAY_FIFO, + IGD_MAX_WM, + IGD_DFT_HPLLOFF_WM, + IGD_GUARD_WM, + IGD_FIFO_LINE_SIZE +}; +static struct intel_watermark_params igd_cursor_wm = { + IGD_CURSOR_FIFO, + IGD_CURSOR_MAX_WM, + IGD_CURSOR_DFT_WM, + IGD_CURSOR_GUARD_WM, + IGD_FIFO_LINE_SIZE, +}; +static struct intel_watermark_params igd_cursor_hplloff_wm = { + IGD_CURSOR_FIFO, + IGD_CURSOR_MAX_WM, + IGD_CURSOR_DFT_WM, + IGD_CURSOR_GUARD_WM, + IGD_FIFO_LINE_SIZE +}; +static struct intel_watermark_params i945_wm_info = { + I915_FIFO_LINE_SIZE, + I915_MAX_WM, + 1, + 0, + IGD_FIFO_LINE_SIZE +}; +static struct intel_watermark_params i915_wm_info = { + I945_FIFO_SIZE, + I915_MAX_WM, + 1, + 0, + I915_FIFO_LINE_SIZE +}; +static struct intel_watermark_params i855_wm_info = { + I855GM_FIFO_SIZE, + I915_MAX_WM, + 1, + 0, + I830_FIFO_LINE_SIZE +}; +static struct intel_watermark_params i830_wm_info = { + I830_FIFO_SIZE, + I915_MAX_WM, + 1, + 0, + I830_FIFO_LINE_SIZE +}; + +static unsigned long intel_calculate_wm(unsigned long clock_in_khz, + struct intel_watermark_params *wm, + int pixel_size, + unsigned long latency_ns) +{ + unsigned long bytes_required, wm_size; + + bytes_required = (clock_in_khz * pixel_size * latency_ns) / 1000000; + bytes_required /= wm->cacheline_size; + wm_size = wm->fifo_size - bytes_required - wm->guard_size; + + if (wm_size > wm->max_wm) + wm_size = wm->max_wm; + if (wm_size == 0) + wm_size = wm->default_wm; + return wm_size; +} + +struct cxsr_latency { + int is_desktop; + unsigned long fsb_freq; + unsigned long mem_freq; + unsigned long display_sr; + unsigned long display_hpll_disable; + unsigned long cursor_sr; + unsigned long cursor_hpll_disable; +}; + +static struct cxsr_latency cxsr_latency_table[] = { + {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ + {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ + {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ + + {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ + {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ + {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ + + {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ + {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ + {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ + + {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ + {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ + {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ + + {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ + {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ + {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ + + {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ + {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ + {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ +}; + +static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, + int mem) +{ + int i; + struct cxsr_latency *latency; + + if (fsb == 0 || mem == 0) + return NULL; + + for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { + latency = &cxsr_latency_table[i]; + if (is_desktop == latency->is_desktop && + fsb == latency->fsb_freq && mem == latency->mem_freq) + break; + } + if (i >= ARRAY_SIZE(cxsr_latency_table)) { + DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); + return NULL; + } + return latency; +} + +static void igd_disable_cxsr(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 reg; + + /* deactivate cxsr */ + reg = I915_READ(DSPFW3); + reg &= ~(IGD_SELF_REFRESH_EN); + I915_WRITE(DSPFW3, reg); + DRM_INFO("Big FIFO is disabled\n"); +} + +static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, + int pixel_size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 reg; + unsigned long wm; + struct cxsr_latency *latency; + + latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq, + dev_priv->mem_freq); + if (!latency) { + DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n"); + igd_disable_cxsr(dev); + return; + } + + /* Display SR */ + wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size, + latency->display_sr); + reg = I915_READ(DSPFW1); + reg &= 0x7fffff; + reg |= wm << 23; + I915_WRITE(DSPFW1, reg); + DRM_DEBUG("DSPFW1 register is %x\n", reg); + + /* cursor SR */ + wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size, + latency->cursor_sr); + reg = I915_READ(DSPFW3); + reg &= ~(0x3f << 24); + reg |= (wm & 0x3f) << 24; + I915_WRITE(DSPFW3, reg); + + /* Display HPLL off SR */ + wm = intel_calculate_wm(clock, &igd_display_hplloff_wm, + latency->display_hpll_disable, I915_FIFO_LINE_SIZE); + reg = I915_READ(DSPFW3); + reg &= 0xfffffe00; + reg |= wm & 0x1ff; + I915_WRITE(DSPFW3, reg); + + /* cursor HPLL off SR */ + wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size, + latency->cursor_hpll_disable); + reg = I915_READ(DSPFW3); + reg &= ~(0x3f << 16); + reg |= (wm & 0x3f) << 16; + I915_WRITE(DSPFW3, reg); + DRM_DEBUG("DSPFW3 register is %x\n", reg); + + /* activate cxsr */ + reg = I915_READ(DSPFW3); + reg |= IGD_SELF_REFRESH_EN; + I915_WRITE(DSPFW3, reg); + + DRM_INFO("Big FIFO is enabled\n"); + + return; +} + +const static int latency_ns = 5000; /* default for non-igd platforms */ + + +static void i965_update_wm(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n"); + + /* 965 has limitations... */ + I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0)); + I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); +} + +static void i9xx_update_wm(struct drm_device *dev, int planea_clock, + int planeb_clock, int sr_hdisplay, int pixel_size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; + uint32_t fwater_hi = I915_READ(FW_BLC2) & LM_FIFO_WATERMARK; + int bsize, asize, cwm, bwm = 1, awm = 1, srwm = 1; + uint32_t dsparb = I915_READ(DSPARB); + int planea_entries, planeb_entries; + struct intel_watermark_params *wm_params; + unsigned long line_time_us; + int sr_clock, sr_entries = 0; + + if (IS_I965GM(dev) || IS_I945GM(dev)) + wm_params = &i945_wm_info; + else if (IS_I9XX(dev)) + wm_params = &i915_wm_info; + else + wm_params = &i855_wm_info; + + planea_entries = intel_calculate_wm(planea_clock, wm_params, + pixel_size, latency_ns); + planeb_entries = intel_calculate_wm(planeb_clock, wm_params, + pixel_size, latency_ns); + + DRM_DEBUG("FIFO entries - A: %d, B: %d\n", planea_entries, + planeb_entries); + + if (IS_I9XX(dev)) { + asize = dsparb & 0x7f; + bsize = (dsparb >> DSPARB_CSTART_SHIFT) & 0x7f; + } else { + asize = dsparb & 0x1ff; + bsize = (dsparb >> DSPARB_BEND_SHIFT) & 0x1ff; + } + DRM_DEBUG("FIFO size - A: %d, B: %d\n", asize, bsize); + + /* Two extra entries for padding */ + awm = asize - (planea_entries + 2); + bwm = bsize - (planeb_entries + 2); + + /* Sanity check against potentially bad FIFO allocations */ + if (awm <= 0) { + /* pipe is on but has too few FIFO entries */ + if (planea_entries != 0) + DRM_DEBUG("plane A needs more FIFO entries\n"); + awm = 1; + } + if (bwm <= 0) { + if (planeb_entries != 0) + DRM_DEBUG("plane B needs more FIFO entries\n"); + bwm = 1; + } + + /* + * Overlay gets an aggressive default since video jitter is bad. + */ + cwm = 2; + + /* Calc sr entries for one pipe configs */ + if (!planea_clock || !planeb_clock) { + sr_clock = planea_clock ? planea_clock : planeb_clock; + line_time_us = (sr_hdisplay * 1000) / sr_clock; + sr_entries = (((latency_ns / line_time_us) + 1) * pixel_size * + sr_hdisplay) / 1000; + sr_entries = roundup(sr_entries / wm_params->cacheline_size, 1); + if (sr_entries < wm_params->fifo_size) + srwm = wm_params->fifo_size - sr_entries; + } + + DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", + awm, bwm, cwm, srwm); + + fwater_lo = fwater_lo | ((bwm & 0x3f) << 16) | (awm & 0x3f); + fwater_hi = fwater_hi | (cwm & 0x1f); + + I915_WRITE(FW_BLC, fwater_lo); + I915_WRITE(FW_BLC2, fwater_hi); + if (IS_I9XX(dev)) + I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f)); +} + +static void i830_update_wm(struct drm_device *dev, int planea_clock, + int pixel_size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t dsparb = I915_READ(DSPARB); + uint32_t fwater_lo = I915_READ(FW_BLC) & MM_FIFO_WATERMARK; + unsigned int asize, awm; + int planea_entries; + + planea_entries = intel_calculate_wm(planea_clock, &i830_wm_info, + pixel_size, latency_ns); + + asize = dsparb & 0x7f; + + awm = asize - planea_entries; + + fwater_lo = fwater_lo | awm; + + I915_WRITE(FW_BLC, fwater_lo); +} + +/** + * intel_update_watermarks - update FIFO watermark values based on current modes + * + * Calculate watermark values for the various WM regs based on current mode + * and plane configuration. + * + * There are several cases to deal with here: + * - normal (i.e. non-self-refresh) + * - self-refresh (SR) mode + * - lines are large relative to FIFO size (buffer can hold up to 2) + * - lines are small relative to FIFO size (buffer can hold more than 2 + * lines), so need to account for TLB latency + * + * The normal calculation is: + * watermark = dotclock * bytes per pixel * latency + * where latency is platform & configuration dependent (we assume pessimal + * values here). + * + * The SR calculation is: + * watermark = (trunc(latency/line time)+1) * surface width * + * bytes per pixel + * where + * line time = htotal / dotclock + * and latency is assumed to be high, as above. + * + * The final value programmed to the register should always be rounded up, + * and include an extra 2 entries to account for clock crossings. + * + * We don't use the sprite, so we can ignore that. And on Crestline we have + * to set the non-SR watermarks to 8. + */ +static void intel_update_watermarks(struct drm_device *dev) +{ + struct drm_crtc *crtc; + struct intel_crtc *intel_crtc; + int sr_hdisplay = 0; + unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; + int enabled = 0, pixel_size = 0; + + if (DSPARB_HWCONTROL(dev)) + return; + + /* Get the clock config from both planes */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + intel_crtc = to_intel_crtc(crtc); + if (crtc->enabled) { + enabled++; + if (intel_crtc->plane == 0) { + DRM_DEBUG("plane A (pipe %d) clock: %d\n", + intel_crtc->pipe, crtc->mode.clock); + planea_clock = crtc->mode.clock; + } else { + DRM_DEBUG("plane B (pipe %d) clock: %d\n", + intel_crtc->pipe, crtc->mode.clock); + planeb_clock = crtc->mode.clock; + } + sr_hdisplay = crtc->mode.hdisplay; + sr_clock = crtc->mode.clock; + if (crtc->fb) + pixel_size = crtc->fb->bits_per_pixel / 8; + else + pixel_size = 4; /* by default */ + } + } + + if (enabled <= 0) + return; + + /* Single pipe configs can enable self refresh */ + if (enabled == 1 && IS_IGD(dev)) + igd_enable_cxsr(dev, sr_clock, pixel_size); + else if (IS_IGD(dev)) + igd_disable_cxsr(dev); + + if (IS_I965G(dev)) + i965_update_wm(dev); + else if (IS_I9XX(dev) || IS_MOBILE(dev)) + i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay, + pixel_size); + else + i830_update_wm(dev, planea_clock, pixel_size); +} + static int intel_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1951,6 +2368,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* Flush the plane changes */ ret = intel_pipe_set_base(crtc, x, y, old_fb); + + intel_update_watermarks(dev); + drm_vblank_post_modeset(dev, pipe); return ret; @@ -2439,6 +2859,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); intel_crtc->pipe = pipe; + intel_crtc->plane = pipe; for (i = 0; i < 256; i++) { intel_crtc->lut_r[i] = i; intel_crtc->lut_g[i] = i; -- GitLab From 788d84bba47ea3eb377f7a3ae4fd1ee84b84877b Mon Sep 17 00:00:00 2001 From: David Woodhouse <dwmw2@infradead.org> Date: Wed, 1 Jul 2009 18:34:52 +0100 Subject: [PATCH 0512/1002] Fix pci_unmap_addr() et al on i386. We can run a 32-bit kernel on boxes with an IOMMU, so we need pci_unmap_addr() etc. to work -- without it, drivers will leak mappings. To be honest, this whole thing looks like it's more pain than it's worth; I'm half inclined to remove the no-op #else case altogether. But this is the minimal fix, which just does the right thing if CONFIG_DMAR is set. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Cc: stable@kernel.org [ for 2.6.30 ] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/include/asm/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 927958d13c196..1ff685ca221ce 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -91,7 +91,7 @@ extern void pci_iommu_alloc(void); #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) -#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG) +#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG) #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME; -- GitLab From a15a519ed6e5e644f5a33c213c00b0c1d3cfe683 Mon Sep 17 00:00:00 2001 From: David Woodhouse <dwmw2@infradead.org> Date: Wed, 1 Jul 2009 18:49:06 +0100 Subject: [PATCH 0513/1002] Fix iommu address space allocation This fixes kernel.org bug #13584. The IOVA code attempted to optimise the insertion of new ranges into the rbtree, with the unfortunate result that some ranges just didn't get inserted into the tree at all. Then those ranges would be handed out more than once, and things kind of go downhill from there. Introduced after 2.6.25 by ddf02886cbe665d67ca750750196ea5bf524b10b ("PCI: iova RB tree setup tweak"). Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Cc: mark gross <mgross@linux.intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/pci/iova.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index 2287116e98224..46dd440e2315d 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c @@ -1,9 +1,19 @@ /* - * Copyright (c) 2006, Intel Corporation. + * Copyright © 2006-2009, Intel Corporation. * - * This file is released under the GPLv2. + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. * - * Copyright (C) 2006-2008 Intel Corporation * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> */ @@ -123,7 +133,15 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad, /* Insert the new_iova into domain rbtree by holding writer lock */ /* Add new node and rebalance tree. */ { - struct rb_node **entry = &((prev)), *parent = NULL; + struct rb_node **entry, *parent = NULL; + + /* If we have 'prev', it's a valid place to start the + insertion. Otherwise, start from the root. */ + if (prev) + entry = &prev; + else + entry = &iovad->rbroot.rb_node; + /* Figure out where to put new node */ while (*entry) { struct iova *this = container_of(*entry, -- GitLab From 6ff4fd05676bc5b5c930bef25901e489f7843660 Mon Sep 17 00:00:00 2001 From: "ling.ma@intel.com" <ling.ma@intel.com> Date: Thu, 25 Jun 2009 10:59:22 +0800 Subject: [PATCH 0514/1002] drm/i915: Set SSC frequency for 8xx chips correctly All 8xx class chips have the 66/48 split, not just 855. Signed-off-by: Ma Ling <ling.ma@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_bios.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 716409a57244b..da22863c05c0a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -195,10 +195,12 @@ parse_general_features(struct drm_i915_private *dev_priv, dev_priv->lvds_use_ssc = general->enable_ssc; if (dev_priv->lvds_use_ssc) { - if (IS_I855(dev_priv->dev)) - dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; - else - dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; + if (IS_I85X(dev_priv->dev)) + dev_priv->lvds_ssc_freq = + general->ssc_freq ? 66 : 48; + else + dev_priv->lvds_ssc_freq = + general->ssc_freq ? 100 : 96; } } } -- GitLab From c85994e4771025ef2a66533eb1a4c6c2217b9cda Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 1 Jul 2009 19:21:24 +0100 Subject: [PATCH 0515/1002] intel-iommu: Ensure that PTE writes are 64-bit atomic, even on i386 Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ec7e032d5ab50..eea1006c860a1 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -222,7 +222,12 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot) static inline u64 dma_pte_addr(struct dma_pte *pte) { - return (pte->val & VTD_PAGE_MASK); +#ifdef CONFIG_64BIT + return pte->val & VTD_PAGE_MASK; +#else + /* Must have a full atomic 64-bit read */ + return __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK; +#endif } static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn) @@ -712,6 +717,8 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, break; if (!dma_pte_present(pte)) { + uint64_t pteval; + tmp_page = alloc_pgtable_page(); if (!tmp_page) { @@ -719,15 +726,15 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, flags); return NULL; } - domain_flush_cache(domain, tmp_page, PAGE_SIZE); - dma_set_pte_pfn(pte, virt_to_dma_pfn(tmp_page)); - /* - * high level table always sets r/w, last level page - * table control read/write - */ - dma_set_pte_readable(pte); - dma_set_pte_writable(pte); - domain_flush_cache(domain, pte, sizeof(*pte)); + domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); + pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; + if (cmpxchg64(&pte->val, 0ULL, pteval)) { + /* Someone else set it while we were thinking; use theirs. */ + free_pgtable_page(tmp_page); + } else { + dma_pte_addr(pte); + domain_flush_cache(domain, pte, sizeof(*pte)); + } } parent = phys_to_virt(dma_pte_addr(pte)); level--; @@ -1666,6 +1673,8 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, } while (nr_pages--) { + uint64_t tmp; + if (!sg_res) { sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset; @@ -1680,17 +1689,17 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, /* We don't need lock here, nobody else * touches the iova range */ - if (unlikely(dma_pte_addr(pte))) { + tmp = cmpxchg64(&pte->val, 0ULL, pteval); + if (tmp) { static int dumps = 5; - printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx)\n", - iov_pfn, pte->val); + printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", + iov_pfn, tmp, (unsigned long long)pteval); if (dumps) { dumps--; debug_dma_dump_mappings(NULL); } WARN_ON(1); } - pte->val = pteval; pte++; if (!nr_pages || (unsigned long)pte >> VTD_PAGE_SHIFT != -- GitLab From d960eea974f5e500c0dcb95a934239cc1f481cfd Mon Sep 17 00:00:00 2001 From: Randy Dunlap <randy.dunlap@oracle.com> Date: Mon, 29 Jun 2009 14:54:11 -0700 Subject: [PATCH 0516/1002] kernel-doc: move ignoring kmemcheck Somehow I managed to generate a diff that put these 2 lines into the wrong function: should have been in dump_struct() instead of in dump_enum(). Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- scripts/kernel-doc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index ed591e9b7d1de..b52d340d759da 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1426,6 +1426,8 @@ sub dump_struct($$) { # strip comments: $members =~ s/\/\*.*?\*\///gos; $nested =~ s/\/\*.*?\*\///gos; + # strip kmemcheck_bitfield_{begin,end}.*; + $members =~ s/kmemcheck_bitfield_.*?;//gos; create_parameterlist($members, ';', $file); check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); @@ -1468,8 +1470,6 @@ sub dump_enum($$) { } } - # strip kmemcheck_bitfield_{begin,end}.*; - $members =~ s/kmemcheck_bitfield_.*?;//gos; output_declaration($declaration_name, 'enum', -- GitLab From 34e19ada994fb9cb3d11873f2b734602e2135f3a Mon Sep 17 00:00:00 2001 From: Matt Fleming <matt@console-pimps.org> Date: Wed, 1 Jul 2009 18:14:18 +0000 Subject: [PATCH 0517/1002] sh: Fix compiler error and include the definition of IS_ERR_VALUE When arch/sh/include/asm/syscall_32.h is included from a file that doesn't also include linux/err.h the following error is produced, In file included from /home/matt/src/kernels/sh-2.6/arch/sh/include/asm/syscall.h:5, from kernel/trace/trace_syscalls.c:3: /home/matt/src/kernels/sh-2.6/arch/sh/include/asm/syscall_32.h: In function 'syscall_get_error': /home/matt/src/kernels/sh-2.6/arch/sh/include/asm/syscall_32.h:28: error: implicit declaration of function 'IS_ERR_VALUE' make[2]: *** [kernel/trace/trace_syscalls.o] Error 1 make[1]: *** [kernel/trace] Error 2 make: *** [kernel] Error 2 Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/include/asm/syscall_32.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h index 5bc34681d9945..6f83f2cc45c16 100644 --- a/arch/sh/include/asm/syscall_32.h +++ b/arch/sh/include/asm/syscall_32.h @@ -3,6 +3,7 @@ #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/err.h> #include <asm/ptrace.h> /* The system call number is given by the user in R3 */ -- GitLab From 1c6a307a54668eda556f499c94e75086aaf8f80f Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Wed, 1 Jul 2009 06:50:31 +0000 Subject: [PATCH 0518/1002] sh: LCDC dcache flush for deferred io Since writenotify on uncached vmas is unsupported in 2.6.31, live with cached framebuffer memory in the deferred io case for now and flush the dcache before forcing refresh. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Magnus damm <damm@igel.co.jp> --- drivers/video/sh_mobile_lcdcfb.c | 53 +++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index f10d2fbeda060..da983b720f080 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> +#include <linux/vmalloc.h> #include <video/sh_mobile_lcdc.h> #include <asm/atomic.h> @@ -33,6 +34,7 @@ struct sh_mobile_lcdc_chan { struct fb_info info; dma_addr_t dma_handle; struct fb_deferred_io defio; + struct scatterlist *sglist; unsigned long frame_end; wait_queue_head_t frame_end_wait; }; @@ -206,16 +208,38 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} #endif +static int sh_mobile_lcdc_sginit(struct fb_info *info, + struct list_head *pagelist) +{ + struct sh_mobile_lcdc_chan *ch = info->par; + unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; + struct page *page; + int nr_pages = 0; + + sg_init_table(ch->sglist, nr_pages_max); + + list_for_each_entry(page, pagelist, lru) + sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0); + + return nr_pages; +} + static void sh_mobile_lcdc_deferred_io(struct fb_info *info, struct list_head *pagelist) { struct sh_mobile_lcdc_chan *ch = info->par; + unsigned int nr_pages; /* enable clocks before accessing hardware */ sh_mobile_lcdc_clk_on(ch->lcdc); + nr_pages = sh_mobile_lcdc_sginit(info, pagelist); + dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); + /* trigger panel update */ lcdc_write_chan(ch, LDSM2R, 1); + + dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); } static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) @@ -846,21 +870,31 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) } for (i = 0; i < j; i++) { - error = register_framebuffer(&priv->ch[i].info); + struct sh_mobile_lcdc_chan *ch = priv->ch + i; + + info = &ch->info; + + if (info->fbdefio) { + priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * + info->fix.smem_len >> PAGE_SHIFT); + if (!priv->ch->sglist) { + dev_err(&pdev->dev, "cannot allocate sglist\n"); + goto err1; + } + } + + error = register_framebuffer(info); if (error < 0) goto err1; - } - for (i = 0; i < j; i++) { - info = &priv->ch[i].info; dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n", pdev->name, - (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? + (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? "mainlcd" : "sublcd", - (int) priv->ch[i].cfg.lcd_cfg.xres, - (int) priv->ch[i].cfg.lcd_cfg.yres, - priv->ch[i].cfg.bpp); + (int) ch->cfg.lcd_cfg.xres, + (int) ch->cfg.lcd_cfg.yres, + ch->cfg.bpp); /* deferred io mode: disable clock to save power */ if (info->fbdefio) @@ -892,6 +926,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) if (!info->device) continue; + if (priv->ch[i].sglist) + vfree(priv->ch[i].sglist); + dma_free_coherent(&pdev->dev, info->fix.smem_len, info->screen_base, priv->ch[i].dma_handle); fb_dealloc_cmap(&info->cmap); -- GitLab From 206a73c102fc480ba072a9388bc2142c303113aa Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 1 Jul 2009 19:30:28 +0100 Subject: [PATCH 0519/1002] intel-iommu: Kill superfluous mapping_lock Since we're using cmpxchg64() anyway (because that's the only way to do an atomic 64-bit store on i386), we might as well ditch the extra locking and just use cmpxchg64() to ensure that we don't add the page twice. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index eea1006c860a1..02223e2e27d43 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -267,7 +267,6 @@ struct dmar_domain { struct iova_domain iovad; /* iova's that belong to this domain */ struct dma_pte *pgd; /* virtual address */ - spinlock_t mapping_lock; /* page table lock */ int gaw; /* max guest address width */ /* adjusted guest address width, 0 is level 2 30-bit */ @@ -701,13 +700,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, struct dma_pte *parent, *pte = NULL; int level = agaw_to_level(domain->agaw); int offset; - unsigned long flags; BUG_ON(!domain->pgd); BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); parent = domain->pgd; - spin_lock_irqsave(&domain->mapping_lock, flags); while (level > 0) { void *tmp_page; @@ -721,11 +718,9 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, tmp_page = alloc_pgtable_page(); - if (!tmp_page) { - spin_unlock_irqrestore(&domain->mapping_lock, - flags); + if (!tmp_page) return NULL; - } + domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; if (cmpxchg64(&pte->val, 0ULL, pteval)) { @@ -740,7 +735,6 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, level--; } - spin_unlock_irqrestore(&domain->mapping_lock, flags); return pte; } @@ -1375,7 +1369,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width) unsigned long sagaw; init_iova_domain(&domain->iovad, DMA_32BIT_PFN); - spin_lock_init(&domain->mapping_lock); spin_lock_init(&domain->iommu_lock); domain_reserve_special_ranges(domain); @@ -3336,7 +3329,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) int adjust_width; init_iova_domain(&domain->iovad, DMA_32BIT_PFN); - spin_lock_init(&domain->mapping_lock); spin_lock_init(&domain->iommu_lock); domain_reserve_special_ranges(domain); -- GitLab From 12682a971160959072c4970da9b7778709f60bc9 Mon Sep 17 00:00:00 2001 From: "ling.ma@intel.com" <ling.ma@intel.com> Date: Tue, 30 Jun 2009 11:35:35 +0800 Subject: [PATCH 0520/1002] drm/i915: enable sdvo lvds scaling function. Currently we implemented basic sdvo lvds function, But except for sdvo lvds fixed mode, we can not switch to other modes, otherwise display get black. The patch handle three operations to enable sdvo lvds. At first duplicate sdvo fixed mode for adjustment, then according to fixed mode line valid all modes, at last adjust input mode to fit our requirement. Acked by Li Peng <peng.li@linux.intel.com> Signed-off-by: Ma Ling <ling.ma@intel.com> Reviewed-by: Ian Romanick <idr@freedesktop.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_sdvo.c | 114 ++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_sdvo_regs.h | 1 + 2 files changed, 103 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f03473779feb4..4f0c30948bc43 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -68,11 +68,22 @@ struct intel_sdvo_priv { * This is set if we treat the device as HDMI, instead of DVI. */ bool is_hdmi; + /** * This is set if we detect output of sdvo device as LVDS. */ bool is_lvds; + /** + * This is sdvo flags for input timing. + */ + uint8_t sdvo_flags; + + /** + * This is sdvo fixed pannel mode pointer + */ + struct drm_display_mode *sdvo_lvds_fixed_mode; + /** * Returned SDTV resolutions allowed for the current format, if the * device reported it. @@ -592,6 +603,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, uint16_t height) { struct intel_sdvo_preferred_input_timing_args args; + struct intel_sdvo_priv *sdvo_priv = output->dev_priv; uint8_t status; memset(&args, 0, sizeof(args)); @@ -599,7 +611,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output, args.width = width; args.height = height; args.interlace = 0; - args.scaled = 0; + + if (sdvo_priv->is_lvds && + (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width || + sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height)) + args.scaled = 1; + intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, &args, sizeof(args)); status = intel_sdvo_read_response(output, NULL, 0); @@ -944,12 +961,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, struct intel_output *output = enc_to_intel_output(encoder); struct intel_sdvo_priv *dev_priv = output->dev_priv; - if (!dev_priv->is_tv) { - /* Make the CRTC code factor in the SDVO pixel multiplier. The - * SDVO device will be told of the multiplier during mode_set. - */ - adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); - } else { + if (dev_priv->is_tv) { struct intel_sdvo_dtd output_dtd; bool success; @@ -980,6 +992,47 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, intel_sdvo_get_preferred_input_timing(output, &input_dtd); intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); + dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; + + drm_mode_set_crtcinfo(adjusted_mode, 0); + + mode->clock = adjusted_mode->clock; + + adjusted_mode->clock *= + intel_sdvo_get_pixel_multiplier(mode); + } else { + return false; + } + } else if (dev_priv->is_lvds) { + struct intel_sdvo_dtd output_dtd; + bool success; + + drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0); + /* Set output timings */ + intel_sdvo_get_dtd_from_mode(&output_dtd, + dev_priv->sdvo_lvds_fixed_mode); + + intel_sdvo_set_target_output(output, + dev_priv->controlled_output); + intel_sdvo_set_output_timing(output, &output_dtd); + + /* Set the input timing to the screen. Assume always input 0. */ + intel_sdvo_set_target_input(output, true, false); + + + success = intel_sdvo_create_preferred_input_timing( + output, + mode->clock / 10, + mode->hdisplay, + mode->vdisplay); + + if (success) { + struct intel_sdvo_dtd input_dtd; + + intel_sdvo_get_preferred_input_timing(output, + &input_dtd); + intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); + dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags; drm_mode_set_crtcinfo(adjusted_mode, 0); @@ -990,6 +1043,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, } else { return false; } + + } else { + /* Make the CRTC code factor in the SDVO pixel multiplier. The + * SDVO device will be told of the multiplier during mode_set. + */ + adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); } return true; } @@ -1033,15 +1092,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, /* We have tried to get input timing in mode_fixup, and filled into adjusted_mode */ - if (sdvo_priv->is_tv) + if (sdvo_priv->is_tv || sdvo_priv->is_lvds) { intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - else + input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags; + } else intel_sdvo_get_dtd_from_mode(&input_dtd, mode); /* If it's a TV, we already set the output timing in mode_fixup. * Otherwise, the output timing is equal to the input timing. */ - if (!sdvo_priv->is_tv) { + if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) { /* Set the output timing to the screen */ intel_sdvo_set_target_output(output, sdvo_priv->controlled_output); @@ -1116,6 +1176,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; } + if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL) + sdvox |= SDVO_STALL_SELECT; intel_sdvo_write_sdvox(output, sdvox); } @@ -1276,6 +1338,17 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, if (sdvo_priv->pixel_clock_max < mode->clock) return MODE_CLOCK_HIGH; + if (sdvo_priv->is_lvds == true) { + if (sdvo_priv->sdvo_lvds_fixed_mode == NULL) + return MODE_PANEL; + + if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay) + return MODE_PANEL; + + if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay) + return MODE_PANEL; + } + return MODE_OK; } @@ -1549,6 +1622,8 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + struct drm_display_mode *newmode; /* * Attempt to get the mode list from DDC. @@ -1557,11 +1632,10 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) */ intel_ddc_get_modes(intel_output); if (list_empty(&connector->probed_modes) == false) - return; + goto end; /* Fetch modes from VBT */ if (dev_priv->sdvo_lvds_vbt_mode != NULL) { - struct drm_display_mode *newmode; newmode = drm_mode_duplicate(connector->dev, dev_priv->sdvo_lvds_vbt_mode); if (newmode != NULL) { @@ -1571,6 +1645,16 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) drm_mode_probed_add(connector, newmode); } } + +end: + list_for_each_entry(newmode, &connector->probed_modes, head) { + if (newmode->type & DRM_MODE_TYPE_PREFERRED) { + sdvo_priv->sdvo_lvds_fixed_mode = + drm_mode_duplicate(connector->dev, newmode); + break; + } + } + } static int intel_sdvo_get_modes(struct drm_connector *connector) @@ -1593,14 +1677,20 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) static void intel_sdvo_destroy(struct drm_connector *connector) { struct intel_output *intel_output = to_intel_output(connector); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; if (intel_output->i2c_bus) intel_i2c_destroy(intel_output->i2c_bus); if (intel_output->ddc_bus) intel_i2c_destroy(intel_output->ddc_bus); + if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) + drm_mode_destroy(connector->dev, + sdvo_priv->sdvo_lvds_fixed_mode); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); + kfree(intel_output); } diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 193938b7d7f9e..ba5cdf8ae40be 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -715,6 +715,7 @@ struct intel_sdvo_enhancements_arg { #define SDVO_HBUF_TX_ONCE (2 << 6) #define SDVO_HBUF_TX_VSYNC (3 << 6) #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c +#define SDVO_NEED_TO_STALL (1 << 7) struct intel_sdvo_encode{ u8 dvi_rev; -- GitLab From 85b98276f2ffa66b25ae6328b00bfadfd74b74e7 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 1 Jul 2009 19:27:53 +0100 Subject: [PATCH 0521/1002] intel-iommu: Warn about unmatched unmap requests This would have found the bug in i386 pci_unmap_addr() a long time ago. We shouldn't just silently return without doing anything. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 02223e2e27d43..2bbc3fc88dc9f 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2640,7 +2640,8 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, iommu = domain_get_iommu(domain); iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); - if (!iova) + if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n", + (unsigned long long)dev_addr)) return; start_pfn = mm_to_dma_pfn(iova->pfn_lo); @@ -2730,7 +2731,8 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, iommu = domain_get_iommu(domain); iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); - if (!iova) + if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n", + (unsigned long long)sglist[0].dma_address)) return; start_pfn = mm_to_dma_pfn(iova->pfn_lo); -- GitLab From 7766a3fb905f0b078b05f5d6a6be8df4c64b9f51 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Wed, 1 Jul 2009 20:27:03 +0100 Subject: [PATCH 0522/1002] intel-iommu: Use cmpxchg64_local() for setting PTEs Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 2bbc3fc88dc9f..2c1b2babfdc50 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1682,7 +1682,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, /* We don't need lock here, nobody else * touches the iova range */ - tmp = cmpxchg64(&pte->val, 0ULL, pteval); + tmp = cmpxchg64_local(&pte->val, 0ULL, pteval); if (tmp) { static int dumps = 5; printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n", -- GitLab From 43cbcd8acb4c992cbd22d1ec8a08c0591be5d719 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Wed, 1 Jul 2009 12:28:37 -0300 Subject: [PATCH 0523/1002] perf_counter tools: Share rbtree.with the kernel The tools/perf/util/rbtree.c copy already drifted by three csets: 4b324126e0c6c3a5080ca3ec0981e8766ed6f1ee 4c60117811171d867d4f27f17ea07d7419d45dae 16c047add3ceaf0ab882e3e094d1ec904d02312d So remove the copy and use the lib/rbtree.c directly, sharing the source code while still generating a separate object file, since tools/perf uses a far more agressive -O6 switch. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20090701152837.GG15682@ghostprotocols.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 7 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/callchain.h | 2 +- tools/perf/util/include/linux/kernel.h | 21 ++ tools/perf/util/include/linux/module.h | 6 + tools/perf/util/include/linux/rbtree.h | 1 + tools/perf/util/rbtree.c | 383 ------------------------- tools/perf/util/rbtree.h | 171 ----------- tools/perf/util/strlist.h | 2 +- tools/perf/util/symbol.h | 2 +- 12 files changed, 39 insertions(+), 562 deletions(-) create mode 100644 tools/perf/util/include/linux/kernel.h create mode 100644 tools/perf/util/include/linux/module.h create mode 100644 tools/perf/util/include/linux/rbtree.h delete mode 100644 tools/perf/util/rbtree.c delete mode 100644 tools/perf/util/rbtree.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index eddf076b19d7c..c4f48825a6ebc 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -223,7 +223,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ # Those must not be GNU-specific; they are shared with perl/ which may # be built by a different compiler. (Note that this is an artifact now # but it still might be nice to keep that distinction.) -BASIC_CFLAGS = +BASIC_CFLAGS = -Iutil/include BASIC_LDFLAGS = # Guard against environment variables @@ -289,10 +289,10 @@ export PERL_PATH LIB_FILE=libperf.a LIB_H += ../../include/linux/perf_counter.h +LIB_H += ../../include/linux/rbtree.h LIB_H += perf.h LIB_H += util/types.h LIB_H += util/list.h -LIB_H += util/rbtree.h LIB_H += util/levenshtein.h LIB_H += util/parse-options.h LIB_H += util/parse-events.h @@ -691,6 +691,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS util/config.o: util/config.c PERF-CFLAGS $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS + $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< + perf-%$X: %.o $(PERFLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6cba70daf1215..1960c22b816c1 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -12,7 +12,7 @@ #include "util/color.h" #include "util/list.h" #include "util/cache.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/symbol.h" #include "util/string.h" diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 007363db3b16a..0d35e2b8881f5 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -12,7 +12,7 @@ #include "util/color.h" #include "util/list.h" #include "util/cache.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/symbol.h" #include "util/string.h" #include "util/callchain.h" diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5f5e7df8302d0..cdc74cfb15178 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -23,7 +23,7 @@ #include "util/symbol.h" #include "util/color.h" #include "util/util.h" -#include "util/rbtree.h" +#include <linux/rbtree.h> #include "util/parse-options.h" #include "util/parse-events.h" diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 251d99ecd2255..0606b8fd05a11 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -3,7 +3,7 @@ #include "../perf.h" #include "list.h" -#include "rbtree.h" +#include <linux/rbtree.h> #include "symbol.h" diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h new file mode 100644 index 0000000000000..99c1b3d1edd9c --- /dev/null +++ b/tools/perf/util/include/linux/kernel.h @@ -0,0 +1,21 @@ +#ifndef PERF_LINUX_KERNEL_H_ +#define PERF_LINUX_KERNEL_H_ + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) * __mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) +#endif + +#endif diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/module.h new file mode 100644 index 0000000000000..b43e2dc21e04d --- /dev/null +++ b/tools/perf/util/include/linux/module.h @@ -0,0 +1,6 @@ +#ifndef PERF_LINUX_MODULE_H +#define PERF_LINUX_MODULE_H + +#define EXPORT_SYMBOL(name) + +#endif diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h new file mode 100644 index 0000000000000..7a243a143037f --- /dev/null +++ b/tools/perf/util/include/linux/rbtree.h @@ -0,0 +1 @@ +#include "../../../../include/linux/rbtree.h" diff --git a/tools/perf/util/rbtree.c b/tools/perf/util/rbtree.c deleted file mode 100644 index b15ba9c7cb3f2..0000000000000 --- a/tools/perf/util/rbtree.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli <andrea@suse.de> - (C) 2002 David Woodhouse <dwmw2@infradead.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -*/ - -#include "rbtree.h" - -static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *right = node->rb_right; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_right = right->rb_left)) - rb_set_parent(right->rb_left, node); - right->rb_left = node; - - rb_set_parent(right, parent); - - if (parent) - { - if (node == parent->rb_left) - parent->rb_left = right; - else - parent->rb_right = right; - } - else - root->rb_node = right; - rb_set_parent(node, right); -} - -static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *left = node->rb_left; - struct rb_node *parent = rb_parent(node); - - if ((node->rb_left = left->rb_right)) - rb_set_parent(left->rb_right, node); - left->rb_right = node; - - rb_set_parent(left, parent); - - if (parent) - { - if (node == parent->rb_right) - parent->rb_right = left; - else - parent->rb_left = left; - } - else - root->rb_node = left; - rb_set_parent(node, left); -} - -void rb_insert_color(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *parent, *gparent; - - while ((parent = rb_parent(node)) && rb_is_red(parent)) - { - gparent = rb_parent(parent); - - if (parent == gparent->rb_left) - { - { - register struct rb_node *uncle = gparent->rb_right; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_right == node) - { - register struct rb_node *tmp; - __rb_rotate_left(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_right(gparent, root); - } else { - { - register struct rb_node *uncle = gparent->rb_left; - if (uncle && rb_is_red(uncle)) - { - rb_set_black(uncle); - rb_set_black(parent); - rb_set_red(gparent); - node = gparent; - continue; - } - } - - if (parent->rb_left == node) - { - register struct rb_node *tmp; - __rb_rotate_right(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - rb_set_black(parent); - rb_set_red(gparent); - __rb_rotate_left(gparent, root); - } - } - - rb_set_black(root->rb_node); -} - -static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, - struct rb_root *root) -{ - struct rb_node *other; - - while ((!node || rb_is_black(node)) && node != root->rb_node) - { - if (parent->rb_left == node) - { - other = parent->rb_right; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_left(parent, root); - other = parent->rb_right; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_right || rb_is_black(other->rb_right)) - { - rb_set_black(other->rb_left); - rb_set_red(other); - __rb_rotate_right(other, root); - other = parent->rb_right; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - rb_set_black(other->rb_right); - __rb_rotate_left(parent, root); - node = root->rb_node; - break; - } - } - else - { - other = parent->rb_left; - if (rb_is_red(other)) - { - rb_set_black(other); - rb_set_red(parent); - __rb_rotate_right(parent, root); - other = parent->rb_left; - } - if ((!other->rb_left || rb_is_black(other->rb_left)) && - (!other->rb_right || rb_is_black(other->rb_right))) - { - rb_set_red(other); - node = parent; - parent = rb_parent(node); - } - else - { - if (!other->rb_left || rb_is_black(other->rb_left)) - { - rb_set_black(other->rb_right); - rb_set_red(other); - __rb_rotate_left(other, root); - other = parent->rb_left; - } - rb_set_color(other, rb_color(parent)); - rb_set_black(parent); - rb_set_black(other->rb_left); - __rb_rotate_right(parent, root); - node = root->rb_node; - break; - } - } - } - if (node) - rb_set_black(node); -} - -void rb_erase(struct rb_node *node, struct rb_root *root) -{ - struct rb_node *child, *parent; - int color; - - if (!node->rb_left) - child = node->rb_right; - else if (!node->rb_right) - child = node->rb_left; - else - { - struct rb_node *old = node, *left; - - node = node->rb_right; - while ((left = node->rb_left) != NULL) - node = left; - child = node->rb_right; - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent == old) { - parent->rb_right = child; - parent = node; - } else - parent->rb_left = child; - - node->rb_parent_color = old->rb_parent_color; - node->rb_right = old->rb_right; - node->rb_left = old->rb_left; - - if (rb_parent(old)) - { - if (rb_parent(old)->rb_left == old) - rb_parent(old)->rb_left = node; - else - rb_parent(old)->rb_right = node; - } else - root->rb_node = node; - - rb_set_parent(old->rb_left, node); - if (old->rb_right) - rb_set_parent(old->rb_right, node); - goto color; - } - - parent = rb_parent(node); - color = rb_color(node); - - if (child) - rb_set_parent(child, parent); - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - color: - if (color == RB_BLACK) - __rb_erase_color(child, parent, root); -} - -/* - * This function returns the first node (in sort order) of the tree. - */ -struct rb_node *rb_first(const struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_left) - n = n->rb_left; - return n; -} - -struct rb_node *rb_last(const struct rb_root *root) -{ - struct rb_node *n; - - n = root->rb_node; - if (!n) - return NULL; - while (n->rb_right) - n = n->rb_right; - return n; -} - -struct rb_node *rb_next(const struct rb_node *node) -{ - struct rb_node *parent; - - if (rb_parent(node) == node) - return NULL; - - /* If we have a right-hand child, go down and then left as far - as we can. */ - if (node->rb_right) { - node = node->rb_right; - while (node->rb_left) - node=node->rb_left; - return (struct rb_node *)node; - } - - /* No right-hand children. Everything down and left is - smaller than us, so any 'next' node must be in the general - direction of our parent. Go up the tree; any time the - ancestor is a right-hand child of its parent, keep going - up. First time it's a left-hand child of its parent, said - parent is our 'next' node. */ - while ((parent = rb_parent(node)) && node == parent->rb_right) - node = parent; - - return parent; -} - -struct rb_node *rb_prev(const struct rb_node *node) -{ - struct rb_node *parent; - - if (rb_parent(node) == node) - return NULL; - - /* If we have a left-hand child, go down and then right as far - as we can. */ - if (node->rb_left) { - node = node->rb_left; - while (node->rb_right) - node=node->rb_right; - return (struct rb_node *)node; - } - - /* No left-hand children. Go up till we find an ancestor which - is a right-hand child of its parent */ - while ((parent = rb_parent(node)) && node == parent->rb_left) - node = parent; - - return parent; -} - -void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root) -{ - struct rb_node *parent = rb_parent(victim); - - /* Set the surrounding nodes to point to the replacement */ - if (parent) { - if (victim == parent->rb_left) - parent->rb_left = new; - else - parent->rb_right = new; - } else { - root->rb_node = new; - } - if (victim->rb_left) - rb_set_parent(victim->rb_left, new); - if (victim->rb_right) - rb_set_parent(victim->rb_right, new); - - /* Copy the pointers/colour from the victim to the replacement */ - *new = *victim; -} diff --git a/tools/perf/util/rbtree.h b/tools/perf/util/rbtree.h deleted file mode 100644 index 6bdc488a47fba..0000000000000 --- a/tools/perf/util/rbtree.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - Red Black Trees - (C) 1999 Andrea Arcangeli <andrea@suse.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/include/linux/rbtree.h - - To use rbtrees you'll have to implement your own insert and search cores. - This will avoid us to use callbacks and to drop drammatically performances. - I know it's not the cleaner way, but in C (not in C++) to get - performances and genericity... - - Some example of insert and search follows here. The search is a plain - normal search over an ordered tree. The insert instead must be implemented - int two steps: as first thing the code must insert the element in - order as a red leaf in the tree, then the support library function - rb_insert_color() must be called. Such function will do the - not trivial work to rebalance the rbtree if necessary. - ------------------------------------------------------------------------ -static inline struct page * rb_search_page_cache(struct inode * inode, - unsigned long offset) -{ - struct rb_node * n = inode->i_rb_page_cache.rb_node; - struct page * page; - - while (n) - { - page = rb_entry(n, struct page, rb_page_cache); - - if (offset < page->offset) - n = n->rb_left; - else if (offset > page->offset) - n = n->rb_right; - else - return page; - } - return NULL; -} - -static inline struct page * __rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct rb_node ** p = &inode->i_rb_page_cache.rb_node; - struct rb_node * parent = NULL; - struct page * page; - - while (*p) - { - parent = *p; - page = rb_entry(parent, struct page, rb_page_cache); - - if (offset < page->offset) - p = &(*p)->rb_left; - else if (offset > page->offset) - p = &(*p)->rb_right; - else - return page; - } - - rb_link_node(node, parent, p); - - return NULL; -} - -static inline struct page * rb_insert_page_cache(struct inode * inode, - unsigned long offset, - struct rb_node * node) -{ - struct page * ret; - if ((ret = __rb_insert_page_cache(inode, offset, node))) - goto out; - rb_insert_color(node, &inode->i_rb_page_cache); - out: - return ret; -} ------------------------------------------------------------------------ -*/ - -#ifndef _LINUX_RBTREE_H -#define _LINUX_RBTREE_H - -#include <stddef.h> - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -struct rb_node -{ - unsigned long rb_parent_color; -#define RB_RED 0 -#define RB_BLACK 1 - struct rb_node *rb_right; - struct rb_node *rb_left; -} __attribute__((aligned(sizeof(long)))); - /* The alignment might seem pointless, but allegedly CRIS needs it */ - -struct rb_root -{ - struct rb_node *rb_node; -}; - - -#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) -#define rb_color(r) ((r)->rb_parent_color & 1) -#define rb_is_red(r) (!rb_color(r)) -#define rb_is_black(r) rb_color(r) -#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) -#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) - -static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) -{ - rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; -} -static inline void rb_set_color(struct rb_node *rb, int color) -{ - rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; -} - -#define RB_ROOT (struct rb_root) { NULL, } -#define rb_entry(ptr, type, member) container_of(ptr, type, member) - -#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) -#define RB_EMPTY_NODE(node) (rb_parent(node) == node) -#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) - -extern void rb_insert_color(struct rb_node *, struct rb_root *); -extern void rb_erase(struct rb_node *, struct rb_root *); - -/* Find logical next and previous nodes in a tree */ -extern struct rb_node *rb_next(const struct rb_node *); -extern struct rb_node *rb_prev(const struct rb_node *); -extern struct rb_node *rb_first(const struct rb_root *); -extern struct rb_node *rb_last(const struct rb_root *); - -/* Fast replacement of a single node without remove/rebalance/add/rebalance */ -extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, - struct rb_root *root); - -static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, - struct rb_node ** rb_link) -{ - node->rb_parent_color = (unsigned long )parent; - node->rb_left = node->rb_right = NULL; - - *rb_link = node; -} - -#endif /* _LINUX_RBTREE_H */ diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index 2fb117fb4b676..2fdcfee87586a 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h @@ -1,7 +1,7 @@ #ifndef STRLIST_H_ #define STRLIST_H_ -#include "rbtree.h" +#include <linux/rbtree.h> #include <stdbool.h> struct str_node { diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2c48ace8203bc..3a275db1fa64c 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -4,7 +4,7 @@ #include <linux/types.h> #include "types.h" #include "list.h" -#include "rbtree.h" +#include <linux/rbtree.h> struct symbol { struct rb_node rb_node; -- GitLab From 5da50258584469ddfee6545feb4eb2252a8d7e7b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Wed, 1 Jul 2009 14:46:08 -0300 Subject: [PATCH 0524/1002] perf_counter tools: Share list.h with the kernel The copy we were using came from another copy I did for the dwarves (pahole) package, that came from the kernel years ago. The only function that is used by the perf tools and that isn't in the kernel is list_del_range, that I'm leaving in the perf tools only for now. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <20090701174608.GA5823@ghostprotocols.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 3 +- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/util/callchain.h | 2 +- tools/perf/util/include/asm/system.h | 1 + tools/perf/util/include/linux/list.h | 18 + tools/perf/util/include/linux/poison.h | 1 + tools/perf/util/include/linux/prefetch.h | 6 + tools/perf/util/list.h | 603 ----------------------- tools/perf/util/symbol.h | 2 +- 10 files changed, 32 insertions(+), 608 deletions(-) create mode 100644 tools/perf/util/include/asm/system.h create mode 100644 tools/perf/util/include/linux/list.h create mode 100644 tools/perf/util/include/linux/poison.h create mode 100644 tools/perf/util/include/linux/prefetch.h delete mode 100644 tools/perf/util/list.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c4f48825a6ebc..8f7fd1b050a57 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -290,9 +290,10 @@ LIB_FILE=libperf.a LIB_H += ../../include/linux/perf_counter.h LIB_H += ../../include/linux/rbtree.h +LIB_H += ../../include/linux/list.h +LIB_H += util/include/linux/list.h LIB_H += perf.h LIB_H += util/types.h -LIB_H += util/list.h LIB_H += util/levenshtein.h LIB_H += util/parse-options.h LIB_H += util/parse-events.h diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 1960c22b816c1..132de8b28dbb0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -10,7 +10,7 @@ #include "util/util.h" #include "util/color.h" -#include "util/list.h" +#include <linux/list.h> #include "util/cache.h" #include <linux/rbtree.h> #include "util/symbol.h" diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0d35e2b8881f5..be1b7584796dd 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -10,7 +10,7 @@ #include "util/util.h" #include "util/color.h" -#include "util/list.h" +#include <linux/list.h> #include "util/cache.h" #include <linux/rbtree.h> #include "util/symbol.h" diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 0606b8fd05a11..e9bd5e882f38e 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -2,7 +2,7 @@ #define __PERF_CALLCHAIN_H #include "../perf.h" -#include "list.h" +#include <linux/list.h> #include <linux/rbtree.h> #include "symbol.h" diff --git a/tools/perf/util/include/asm/system.h b/tools/perf/util/include/asm/system.h new file mode 100644 index 0000000000000..710cecca972da --- /dev/null +++ b/tools/perf/util/include/asm/system.h @@ -0,0 +1 @@ +/* Empty */ diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h new file mode 100644 index 0000000000000..dbe4b814382ac --- /dev/null +++ b/tools/perf/util/include/linux/list.h @@ -0,0 +1,18 @@ +#include "../../../../include/linux/list.h" + +#ifndef PERF_LIST_H +#define PERF_LIST_H +/** + * list_del_range - deletes range of entries from list. + * @begin: first element in the range to delete from the list. + * @end: last element in the range to delete from the list. + * Note: list_empty on the range of entries does not return true after this, + * the entries is in an undefined state. + */ +static inline void list_del_range(struct list_head *begin, + struct list_head *end) +{ + begin->prev->next = end->next; + end->next->prev = begin->prev; +} +#endif diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h new file mode 100644 index 0000000000000..fef6dbc9ce13b --- /dev/null +++ b/tools/perf/util/include/linux/poison.h @@ -0,0 +1 @@ +#include "../../../../include/linux/poison.h" diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h new file mode 100644 index 0000000000000..7841e485d8c36 --- /dev/null +++ b/tools/perf/util/include/linux/prefetch.h @@ -0,0 +1,6 @@ +#ifndef PERF_LINUX_PREFETCH_H +#define PERF_LINUX_PREFETCH_H + +static inline void prefetch(void *a __attribute__((unused))) { } + +#endif diff --git a/tools/perf/util/list.h b/tools/perf/util/list.h deleted file mode 100644 index e2548e8072cfb..0000000000000 --- a/tools/perf/util/list.h +++ /dev/null @@ -1,603 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H -/* - Copyright (C) Cast of dozens, comes from the Linux kernel - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. -*/ - -#include <stddef.h> - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *)0x00100100) -#define LIST_POISON2 ((void *)0x00200200) - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_range - deletes range of entries from list. - * @beging: first element in the range to delete from the list. - * @beging: first element in the range to delete from the list. - * Note: list_empty on the range of entries does not return true after this, - * the entries is in an undefined state. - */ -static inline void list_del_range(struct list_head *begin, - struct list_head *end) -{ - begin->prev->next = end->next; - end->next->prev = begin->prev; -} - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * Note: if 'old' was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) -{ - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, - struct list_head *new) -{ - list_replace(old, new); - INIT_LIST_HEAD(old); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_is_last - tests whether @list is the last entry in list @head - * @list: the entry to test - * @head: the head of the list - */ -static inline int list_is_last(const struct list_head *list, - const struct list_head *head) -{ - return list->next == head; -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @head: the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member) \ - for (; &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_continue - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_from - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member) \ - for (n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_safe_reverse - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - n = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, typeof(*n), member)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -static inline void INIT_HLIST_NODE(struct hlist_node *h) -{ - h->next = NULL; - h->pprev = NULL; -} - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (!hlist_unhashed(n)) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos; \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from current point - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop cursor. - * @pos: the &struct hlist_node to use as a loop cursor. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -#endif diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 3a275db1fa64c..65a8449b91f52 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -3,7 +3,7 @@ #include <linux/types.h> #include "types.h" -#include "list.h" +#include <linux/list.h> #include <linux/rbtree.h> struct symbol { -- GitLab From 0406ca6d8e849d9dd027c8cb6791448e81411aef Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Wed, 1 Jul 2009 21:02:09 +0200 Subject: [PATCH 0525/1002] perf_counter: Ignore the nmi call frames in the x86-64 backtraces About every callchains recorded with perf record are filled up including the internal perfcounter nmi frame: perf_callchain perf_counter_overflow intel_pmu_handle_irq perf_counter_nmi_handler notifier_call_chain atomic_notifier_call_chain notify_die do_nmi nmi We want ignore this frame as it's not interesting for instrumentation. To solve this, we simply ignore every frames from nmi context. New example of "perf report -s sym -c" after this patch: 9.59% [k] search_by_key 4.88% search_by_key reiserfs_read_locked_inode reiserfs_iget reiserfs_lookup do_lookup __link_path_walk path_walk do_path_lookup user_path_at vfs_fstatat vfs_lstat sys_newlstat system_call_fastpath __lxstat 0x406fb1 3.19% search_by_key search_by_entry_key reiserfs_find_entry reiserfs_lookup do_lookup __link_path_walk path_walk do_path_lookup user_path_at vfs_fstatat vfs_lstat sys_newlstat system_call_fastpath __lxstat 0x406fb1 [...] For now this patch only solves the problem in x86-64. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246474930-6088-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/stacktrace.h | 2 ++ arch/x86/kernel/cpu/perf_counter.c | 8 +++++++- arch/x86/kernel/dumpstack_32.c | 6 ++++++ arch/x86/kernel/dumpstack_64.c | 22 +++++++++++++++------- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index f517944b2b176..cf86a5e73815d 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -3,6 +3,8 @@ extern int kstack_depth_to_print; +int x86_is_stack_id(int id, char *name); + /* Generic stack tracer with callbacks */ struct stacktrace_ops { diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index d4cf4ce19aac5..36c3dc7b8991d 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c @@ -1561,6 +1561,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip) static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry); static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry); +static DEFINE_PER_CPU(int, in_nmi_frame); static void @@ -1576,7 +1577,9 @@ static void backtrace_warning(void *data, char *msg) static int backtrace_stack(void *data, char *name) { - /* Process all stacks: */ + per_cpu(in_nmi_frame, smp_processor_id()) = + x86_is_stack_id(NMI_STACK, name); + return 0; } @@ -1584,6 +1587,9 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) { struct perf_callchain_entry *entry = data; + if (per_cpu(in_nmi_frame, smp_processor_id())) + return; + if (reliable) callchain_store(entry, addr); } diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index d593cd1f58dcc..bca5fba91c9ea 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -19,6 +19,12 @@ #include "dumpstack.h" +/* Just a stub for now */ +int x86_is_stack_id(int id, char *name) +{ + return 0; +} + void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data) diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index d35db5993fd68..54b0a3276766c 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -19,10 +19,8 @@ #include "dumpstack.h" -static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, - unsigned *usedp, char **idp) -{ - static char ids[][8] = { + +static char x86_stack_ids[][8] = { [DEBUG_STACK - 1] = "#DB", [NMI_STACK - 1] = "NMI", [DOUBLEFAULT_STACK - 1] = "#DF", @@ -33,6 +31,15 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" #endif }; + +int x86_is_stack_id(int id, char *name) +{ + return x86_stack_ids[id - 1] == name; +} + +static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, + unsigned *usedp, char **idp) +{ unsigned k; /* @@ -61,7 +68,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, if (*usedp & (1U << k)) break; *usedp |= 1U << k; - *idp = ids[k]; + *idp = x86_stack_ids[k]; return (unsigned long *)end; } /* @@ -81,12 +88,13 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, do { ++j; end -= EXCEPTION_STKSZ; - ids[j][4] = '1' + (j - N_EXCEPTION_STACKS); + x86_stack_ids[j][4] = '1' + + (j - N_EXCEPTION_STACKS); } while (stack < end - EXCEPTION_STKSZ); if (*usedp & (1U << j)) break; *usedp |= 1U << j; - *idp = ids[j]; + *idp = x86_stack_ids[j]; return (unsigned long *)end; } #endif -- GitLab From a92bef0f216bbf3d05c0c0709ea02e267f2b920e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Wed, 1 Jul 2009 21:02:10 +0200 Subject: [PATCH 0526/1002] perf stat: Handle pipe read failures in perf stat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building builtin-stat.c reports the following errors: cc1: warnings being treated as errors builtin-stat.c: In function ‘run_perf_stat’: builtin-stat.c:242: erreur: ignoring return value of ‘read’, declared with attribute warn_unused_result builtin-stat.c:255: erreur: ignoring return value of ‘read’, declared with attribute warn_unused_result make: *** [builtin-stat.o] Erreur 1 This patch handles the possible pipe read failures. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246474930-6088-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-stat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 01cc07efb728a..27921a8ce1a9a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -239,7 +239,8 @@ static int run_perf_stat(int argc __used, const char **argv) /* * Wait until the parent tells us to go. */ - read(go_pipe[0], &buf, 1); + if (read(go_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); execvp(argv[0], (char **)argv); @@ -252,7 +253,8 @@ static int run_perf_stat(int argc __used, const char **argv) */ close(child_ready_pipe[1]); close(go_pipe[0]); - read(child_ready_pipe[0], &buf, 1); + if (read(child_ready_pipe[0], &buf, 1) == -1) + perror("unable to read pipe"); close(child_ready_pipe[0]); for (counter = 0; counter < nr_counters; counter++) -- GitLab From 46b952a3c3a94afa339bd4961a4f3d1482436599 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox <matthew@wil.cx> Date: Wed, 1 Jul 2009 14:24:30 -0700 Subject: [PATCH 0527/1002] PCI: Fix IRQ swizzling for ARI-enabled devices For many purposes, including interrupt-swizzling, devices with ARI enabled behave as if they have one device (number 0) and 256 functions. This probably hasn't bitten us in practice because all ARI devices I've seen are also IOV devices, and IOV devices are required to use MSI. This isn't guaranteed, and there are legitimate reasons to use ARI without IOV, and hence potentially use pin-based interrupts. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/pci/pci.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d5d6f5667d831..dbd0f947f4972 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1517,11 +1517,20 @@ void pci_enable_ari(struct pci_dev *dev) * * Perform INTx swizzling for a device behind one level of bridge. This is * required by section 9.1 of the PCI-to-PCI bridge specification for devices - * behind bridges on add-in cards. + * behind bridges on add-in cards. For devices with ARI enabled, the slot + * number is always 0 (see the Implementation Note in section 2.2.8.1 of + * the PCI Express Base Specification, Revision 2.1) */ u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) { - return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; + int slot; + + if (pci_ari_enabled(dev->bus)) + slot = 0; + else + slot = PCI_SLOT(dev->devfn); + + return (((pin - 1) + slot) % 4) + 1; } int -- GitLab From cc0bad7552308e8905d6ea56e6b7811fa67e716d Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 25 Jun 2009 00:56:52 -0400 Subject: [PATCH 0528/1002] cifs: add new cifs_iget function and convert unix codepath to use it cifs: add new cifs_iget function and convert unix codepath to use it In order to unify some codepaths, introduce a common cifs_fattr struct for storing inode attributes. The different codepaths (unix, legacy, normal, etc...) can fill out this struct with inode info. It can then be passed as an arg to a common set of routines to get and update inodes. Add a new cifs_iget function that uses iget5_locked to identify inodes. This will compare inodes based on the uniqueid value in a cifs_fattr struct. Rather than filling out an already-created inode, have cifs_get_inode_info_unix instead fill out cifs_fattr and hand that off to cifs_iget. cifs_iget can then properly look for hardlinked inodes. On the readdir side, add a new cifs_readdir_lookup function that spawns populated dentries. Redefine FILE_UNIX_INFO so that it's basically a FILE_UNIX_BASIC_INFO that has a few fields wrapped around it. This allows us to more easily use the same function for filling out the fattr as the non-readdir codepath. With this, we should then have proper hardlink detection and can eventually get rid of some nasty CIFS-specific hacks for handing them. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.h | 13 ++ fs/cifs/cifsglob.h | 25 +++ fs/cifs/cifspdu.h | 14 +- fs/cifs/cifsproto.h | 9 +- fs/cifs/dir.c | 22 +-- fs/cifs/inode.c | 380 ++++++++++++++++++++++---------------------- fs/cifs/readdir.c | 253 +++++++++++------------------ 7 files changed, 339 insertions(+), 377 deletions(-) diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023f4..586df24c9abb6 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -24,6 +24,19 @@ #define ROOT_I 2 +/* + * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down + * so that it will fit. + */ +static inline ino_t +cifs_uniqueid_to_ino_t(u64 fileid) +{ + ino_t ino = (ino_t) fileid; + if (sizeof(ino_t) < sizeof(u64)) + ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; + return ino; +} + extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2fc..e6435cba81132 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -371,6 +371,7 @@ struct cifsInodeInfo { bool oplockPending:1; bool delete_pending:1; /* DELETE_ON_CLOSE is set */ u64 server_eof; /* current file size on server */ + u64 uniqueid; /* server inode number */ struct inode vfs_inode; }; @@ -472,6 +473,30 @@ struct dfs_info3_param { char *node_name; }; +/* + * common struct for holding inode info when searching for or updating an + * inode with new info + */ + +#define CIFS_FATTR_DFS_REFERRAL 0x1 + +struct cifs_fattr { + u32 cf_flags; + u32 cf_cifsattrs; + u64 cf_uniqueid; + u64 cf_eof; + u64 cf_bytes; + uid_t cf_uid; + gid_t cf_gid; + umode_t cf_mode; + dev_t cf_rdev; + unsigned int cf_nlink; + unsigned int cf_dtype; + struct timespec cf_atime; + struct timespec cf_mtime; + struct timespec cf_ctime; +}; + static inline void free_dfs_info_param(struct dfs_info3_param *param) { if (param) { diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9fe..2d07f890a842f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -2328,19 +2328,7 @@ struct file_attrib_tag { typedef struct { __le32 NextEntryOffset; __u32 ResumeKey; /* as with FileIndex - no need to convert */ - __le64 EndOfFile; - __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ - __le64 LastAccessTime; - __le64 LastModificationTime; - __le64 Uid; - __le64 Gid; - __le32 Type; - __le64 DevMajor; - __le64 DevMinor; - __le64 UniqueId; - __le64 Permissions; - __le64 Nlinks; + FILE_UNIX_BASIC_INFO basic; char FileName[1]; } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42eef..b2bd83fd2aa48 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -98,9 +98,14 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, extern int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, int *poplock, __u16 *pnetfid, int xid); -extern void posix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_BASIC_INFO *pData, int isNewInode); +extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, + FILE_UNIX_BASIC_INFO *info, + struct cifs_sb_info *cifs_sb); +extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); +extern struct inode *cifs_iget(struct super_block *sb, + struct cifs_fattr *fattr); + extern int cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, FILE_ALL_INFO *pfile_info, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9deff..a40054faed7f6 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, FILE_UNIX_BASIC_INFO *presp_data; __u32 posix_flags = 0; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + struct cifs_fattr fattr; cFYI(1, ("posix open %s", full_path)); @@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, if (presp_data->Type == cpu_to_le32(-1)) goto posix_open_ret; /* open ok, caller does qpathinfo */ - /* get new inode and set it up */ if (!pinode) goto posix_open_ret; /* caller does not need info */ + cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); + + /* get new inode and set it up */ if (*pinode == NULL) { - __u64 unique_id = le64_to_cpu(presp_data->UniqueId); - *pinode = cifs_new_inode(sb, &unique_id); + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) { + rc = -ENOMEM; + goto posix_open_ret; + } + } else { + cifs_fattr_to_inode(*pinode, &fattr); } - /* else an inode was passed in. Update its info, don't create one */ - - /* We do not need to close the file if new_inode fails since - the caller will retry qpathinfo as long as inode is null */ - if (*pinode == NULL) - goto posix_open_ret; - - posix_fill_in_inode(*pinode, presp_data, 1); cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c6..b22379610d719 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -77,127 +77,146 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) } } -static void cifs_unix_info_to_inode(struct inode *inode, - FILE_UNIX_BASIC_INFO *info, int force_uid_gid) +/* populate an inode with info from a cifs_fattr struct */ +void +cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) { - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct cifsInodeInfo *cifsInfo = CIFS_I(inode); - __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); - __u64 end_of_file = le64_to_cpu(info->EndOfFile); + struct cifsInodeInfo *cifs_i = CIFS_I(inode); + unsigned long now = jiffies; + + inode->i_atime = fattr->cf_atime; + inode->i_mtime = fattr->cf_mtime; + inode->i_ctime = fattr->cf_ctime; + inode->i_mode = fattr->cf_mode; + inode->i_rdev = fattr->cf_rdev; + inode->i_nlink = fattr->cf_nlink; + inode->i_uid = fattr->cf_uid; + inode->i_gid = fattr->cf_gid; + + cifs_i->cifsAttrs = fattr->cf_cifsattrs; + cifs_i->uniqueid = fattr->cf_uniqueid; + + cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, + cifs_i->time, now)); + cifs_i->time = now; + + /* + * Can't safely change the file size here if the client is writing to + * it due to potential races. + */ + spin_lock(&inode->i_lock); + if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { + i_size_write(inode, fattr->cf_eof); + + /* + * i_blocks is not related to (i_size / i_blksize), + * but instead 512 byte (2**9) size is required for + * calculating num blocks. + */ + inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; + } + spin_unlock(&inode->i_lock); + + cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); +} + +/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ +void +cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, + struct cifs_sb_info *cifs_sb) +{ + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); + fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); + fattr->cf_eof = le64_to_cpu(info->EndOfFile); - inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); - inode->i_mtime = - cifs_NTtimeToUnix(info->LastModificationTime); - inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); - inode->i_mode = le64_to_cpu(info->Permissions); + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); + fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); + fattr->cf_mode = le64_to_cpu(info->Permissions); /* * Since we set the inode type below we need to mask off * to avoid strange results if bits set above. */ - inode->i_mode &= ~S_IFMT; + fattr->cf_mode &= ~S_IFMT; switch (le32_to_cpu(info->Type)) { case UNIX_FILE: - inode->i_mode |= S_IFREG; + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; break; case UNIX_SYMLINK: - inode->i_mode |= S_IFLNK; + fattr->cf_mode |= S_IFLNK; + fattr->cf_dtype = DT_LNK; break; case UNIX_DIR: - inode->i_mode |= S_IFDIR; + fattr->cf_mode |= S_IFDIR; + fattr->cf_dtype = DT_DIR; break; case UNIX_CHARDEV: - inode->i_mode |= S_IFCHR; - inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); + fattr->cf_mode |= S_IFCHR; + fattr->cf_dtype = DT_CHR; + fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), + le64_to_cpu(info->DevMinor) & MINORMASK); break; case UNIX_BLOCKDEV: - inode->i_mode |= S_IFBLK; - inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), - le64_to_cpu(info->DevMinor) & MINORMASK); + fattr->cf_mode |= S_IFBLK; + fattr->cf_dtype = DT_BLK; + fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), + le64_to_cpu(info->DevMinor) & MINORMASK); break; case UNIX_FIFO: - inode->i_mode |= S_IFIFO; + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; break; case UNIX_SOCKET: - inode->i_mode |= S_IFSOCK; + fattr->cf_mode |= S_IFSOCK; + fattr->cf_dtype = DT_SOCK; break; default: /* safest to call it a file if we do not know */ - inode->i_mode |= S_IFREG; + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); break; } - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && - !force_uid_gid) - inode->i_uid = cifs_sb->mnt_uid; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) + fattr->cf_uid = cifs_sb->mnt_uid; else - inode->i_uid = le64_to_cpu(info->Uid); + fattr->cf_uid = le64_to_cpu(info->Uid); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && - !force_uid_gid) - inode->i_gid = cifs_sb->mnt_gid; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) + fattr->cf_gid = cifs_sb->mnt_gid; else - inode->i_gid = le64_to_cpu(info->Gid); + fattr->cf_gid = le64_to_cpu(info->Gid); - inode->i_nlink = le64_to_cpu(info->Nlinks); - - cifsInfo->server_eof = end_of_file; - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* - * We can not safely change the file size here if the client - * is writing to it due to potential races. - */ - i_size_write(inode, end_of_file); - - /* - * i_blocks is not related to (i_size / i_blksize), - * but instead 512 byte (2**9) size is required for - * calculating num blocks. - */ - inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; - } - spin_unlock(&inode->i_lock); + fattr->cf_nlink = le64_to_cpu(info->Nlinks); } - /* - * Needed to setup inode data for the directory which is the - * junction to the new submount (ie to setup the fake directory - * which represents a DFS referral) + * Fill a cifs_fattr struct with fake inode info. + * + * Needed to setup cifs_fattr data for the directory which is the + * junction to the new submount (ie to setup the fake directory + * which represents a DFS referral). */ -static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, - struct super_block *sb) +void +cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) { - struct inode *pinode = NULL; - - memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -/* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); - __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); - __u64 UniqueId = 0; */ - pfnd_dat->LastStatusChange = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastModificationTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->Type = cpu_to_le32(UNIX_DIR); - pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); - pfnd_dat->Nlinks = cpu_to_le64(2); - if (sb->s_root) - pinode = sb->s_root->d_inode; - if (pinode == NULL) - return; - - /* fill in default values for the remaining based on root - inode since we can not query the server for this inode info */ - pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); - pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); - pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); - pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); + cFYI(1, ("creating fake fattr for DFS referral")); + + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; + fattr->cf_atime = CURRENT_TIME; + fattr->cf_ctime = CURRENT_TIME; + fattr->cf_mtime = CURRENT_TIME; + fattr->cf_nlink = 2; + fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } /** @@ -244,66 +263,42 @@ cifs_new_inode(struct super_block *sb, __u64 *inum) } int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *full_path, struct super_block *sb, int xid) + const unsigned char *full_path, + struct super_block *sb, int xid) { - int rc = 0; + int rc; FILE_UNIX_BASIC_INFO find_data; - struct cifsTconInfo *pTcon; - struct inode *inode; + struct cifs_fattr fattr; + struct cifsTconInfo *tcon; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - bool is_dfs_referral = false; - struct cifsInodeInfo *cifsInfo; - __u64 num_of_bytes; - __u64 end_of_file; - pTcon = cifs_sb->tcon; + tcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); /* could have done a find first instead but this returns more info */ - rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, + rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == -EREMOTE && !is_dfs_referral) { - is_dfs_referral = true; - cFYI(DBG2, ("DFS ref")); - /* for DFS, server does not give us real inode data */ - fill_fake_finddataunix(&find_data, sb); - rc = 0; - } else if (rc) - goto cgiiu_exit; - num_of_bytes = le64_to_cpu(find_data.NumOfBytes); - end_of_file = le64_to_cpu(find_data.EndOfFile); + if (!rc) { + cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, sb); + rc = 0; + } else { + return rc; + } - /* get new inode */ if (*pinode == NULL) { - __u64 unique_id = le64_to_cpu(find_data.UniqueId); - *pinode = cifs_new_inode(sb, &unique_id); - if (*pinode == NULL) { + /* get new inode */ + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) rc = -ENOMEM; - goto cgiiu_exit; - } + } else { + /* we already have inode, update it */ + cifs_fattr_to_inode(*pinode, &fattr); } - inode = *pinode; - cifsInfo = CIFS_I(inode); - - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - /* this is ok to set on every inode revalidate */ - atomic_set(&cifsInfo->inUse, 1); - - cifs_unix_info_to_inode(inode, &find_data, 0); - - if (num_of_bytes < end_of_file) - cFYI(1, ("allocation size less than end of file")); - cFYI(1, ("Size %ld and blocks %llu", - (unsigned long) inode->i_size, - (unsigned long long)inode->i_blocks)); - - cifs_set_ops(inode, is_dfs_referral); -cgiiu_exit: return rc; } @@ -695,33 +690,85 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) return full_path; } +static int +cifs_find_inode(struct inode *inode, void *opaque) +{ + struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; + + if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) + return 0; + + return 1; +} + +static int +cifs_init_inode(struct inode *inode, void *opaque) +{ + struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; + + CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; + return 0; +} + +/* Given fattrs, get a corresponding inode */ +struct inode * +cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) +{ + unsigned long hash; + struct inode *inode; + + cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); + + /* hash down to 32-bits on 32-bit arch */ + hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); + + inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); + + /* we have fattrs in hand, update the inode */ + if (inode) { + cifs_fattr_to_inode(inode, fattr); + if (sb->s_flags & MS_NOATIME) + inode->i_flags |= S_NOATIME | S_NOCMTIME; + if (inode->i_state & I_NEW) { + inode->i_ino = hash; + unlock_new_inode(inode); + } + } + + return inode; +} + /* gets root inode */ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) { int xid; struct cifs_sb_info *cifs_sb; - struct inode *inode; + struct inode *inode = NULL; long rc; char *full_path; - inode = iget_locked(sb, ino); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - - cifs_sb = CIFS_SB(inode->i_sb); + cifs_sb = CIFS_SB(sb); full_path = cifs_build_path_to_root(cifs_sb); if (full_path == NULL) return ERR_PTR(-ENOMEM); xid = GetXid(); - if (cifs_sb->tcon->unix_ext) - rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, - xid); - else + if (cifs_sb->tcon->unix_ext) { + rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); + if (!inode) + return ERR_PTR(-ENOMEM); + } else { + inode = iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + if (!(inode->i_state & I_NEW)) + return inode; + rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, xid, NULL); + unlock_new_inode(inode); + } + if (rc && cifs_sb->tcon->ipc) { cFYI(1, ("ipc connection - fake read inode")); inode->i_mode |= S_IFDIR; @@ -737,7 +784,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) return ERR_PTR(rc); } - unlock_new_inode(inode); kfree(full_path); /* can not call macro FreeXid here since in a void func @@ -1063,44 +1109,6 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) return rc; } -void posix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_BASIC_INFO *pData, int isNewInode) -{ - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - loff_t local_size; - struct timespec local_mtime; - - cifsInfo->time = jiffies; - atomic_inc(&cifsInfo->inUse); - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - cifs_unix_info_to_inode(tmp_inode, pData, 1); - cifs_set_ops(tmp_inode, false); - - if (!S_ISREG(tmp_inode->i_mode)) - return; - - /* - * No sense invalidating pages for new inode - * since we we have not started caching - * readahead file data yet. - */ - if (isNewInode) - return; - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } -} - int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) { int rc = 0, tmprc; @@ -1109,6 +1117,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; + struct cifs_fattr fattr; cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); @@ -1148,7 +1157,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) cFYI(1, ("posix mkdir returned 0x%x", rc)); d_drop(direntry); } else { - __u64 unique_id; if (pInfo->Type == cpu_to_le32(-1)) { /* no return info, go query for it */ kfree(pInfo); @@ -1162,20 +1170,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) else direntry->d_op = &cifs_dentry_ops; - unique_id = le64_to_cpu(pInfo->UniqueId); - newinode = cifs_new_inode(inode->i_sb, &unique_id); - if (newinode == NULL) { + cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); + newinode = cifs_iget(inode->i_sb, &fattr); + if (!newinode) { kfree(pInfo); goto mkdir_get_info; } - newinode->i_nlink = 2; d_instantiate(direntry, newinode); - /* we already checked in POSIXCreate whether - frame was long enough */ - posix_fill_in_inode(direntry->d_inode, - pInfo, 1 /* NewInode */); #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("instantiated dentry %p %s to inode %p", direntry, direntry->d_name.name, newinode)); @@ -1622,6 +1625,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, if (!err) { generic_fillattr(dentry->d_inode, stat); stat->blksize = CIFS_MAX_MSGSIZE; + stat->ino = CIFS_I(dentry->d_inode)->uniqueid; } return err; } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc5299..231aa6953f834 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -63,6 +63,55 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) } #endif /* DEBUG2 */ +/* + * Find the dentry that matches "name". If there isn't one, create one. If it's + * a negative dentry or the uniqueid changed, then drop it and recreate it. + */ +static struct dentry * +cifs_readdir_lookup(struct dentry *parent, struct qstr *name, + struct cifs_fattr *fattr) +{ + struct dentry *dentry, *alias; + struct inode *inode; + struct super_block *sb = parent->d_inode->i_sb; + + cFYI(1, ("For %s", name->name)); + + dentry = d_lookup(parent, name); + if (dentry) { + /* FIXME: check for inode number changes? */ + if (dentry->d_inode != NULL) + return dentry; + d_drop(dentry); + dput(dentry); + } + + dentry = d_alloc(parent, name); + if (dentry == NULL) + return NULL; + + inode = cifs_iget(sb, fattr); + if (!inode) { + dput(dentry); + return NULL; + } + + if (CIFS_SB(sb)->tcon->nocase) + dentry->d_op = &cifs_ci_dentry_ops; + else + dentry->d_op = &cifs_dentry_ops; + + alias = d_materialise_unique(dentry, inode); + if (alias != NULL) { + dput(dentry); + if (IS_ERR(alias)) + return NULL; + dentry = alias; + } + + return dentry; +} + /* Returns 1 if new inode created, 2 if both dentry and inode were */ /* Might check in the future if inode number changed so we can rehash inode */ static int @@ -76,7 +125,6 @@ construct_dentry(struct qstr *qstring, struct file *file, cFYI(1, ("For %s", qstring->name)); - qstring->hash = full_name_hash(qstring->name, qstring->len); tmp_dentry = d_lookup(file->f_path.dentry, qstring); if (tmp_dentry) { /* BB: overwrite old name? i.e. tmp_dentry->d_name and @@ -299,140 +347,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, } } -static void unix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) -{ - loff_t local_size; - struct timespec local_mtime; - - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); - - __u32 type = le32_to_cpu(pfindData->Type); - __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); - __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); - cifsInfo->time = jiffies; - atomic_inc(&cifsInfo->inUse); - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - tmp_inode->i_atime = - cifs_NTtimeToUnix(pfindData->LastAccessTime); - tmp_inode->i_mtime = - cifs_NTtimeToUnix(pfindData->LastModificationTime); - tmp_inode->i_ctime = - cifs_NTtimeToUnix(pfindData->LastStatusChange); - - tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); - /* since we set the inode type below we need to mask off type - to avoid strange results if bits above were corrupt */ - tmp_inode->i_mode &= ~S_IFMT; - if (type == UNIX_FILE) { - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - } else if (type == UNIX_SYMLINK) { - *pobject_type = DT_LNK; - tmp_inode->i_mode |= S_IFLNK; - } else if (type == UNIX_DIR) { - *pobject_type = DT_DIR; - tmp_inode->i_mode |= S_IFDIR; - } else if (type == UNIX_CHARDEV) { - *pobject_type = DT_CHR; - tmp_inode->i_mode |= S_IFCHR; - tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), - le64_to_cpu(pfindData->DevMinor) & MINORMASK); - } else if (type == UNIX_BLOCKDEV) { - *pobject_type = DT_BLK; - tmp_inode->i_mode |= S_IFBLK; - tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), - le64_to_cpu(pfindData->DevMinor) & MINORMASK); - } else if (type == UNIX_FIFO) { - *pobject_type = DT_FIFO; - tmp_inode->i_mode |= S_IFIFO; - } else if (type == UNIX_SOCKET) { - *pobject_type = DT_SOCK; - tmp_inode->i_mode |= S_IFSOCK; - } else { - /* safest to just call it a file */ - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - cFYI(1, ("unknown inode type %d", type)); - } - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) - tmp_inode->i_uid = cifs_sb->mnt_uid; - else - tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) - tmp_inode->i_gid = cifs_sb->mnt_gid; - else - tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); - tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); - - cifsInfo->server_eof = end_of_file; - spin_lock(&tmp_inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* can not safely change the file size here if the - client is writing to it due to potential races */ - i_size_write(tmp_inode, end_of_file); - - /* 512 bytes (2**9) is the fake blocksize that must be used */ - /* for this calculation, not the real blocksize */ - tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; - } - spin_unlock(&tmp_inode->i_lock); - - if (S_ISREG(tmp_inode->i_mode)) { - cFYI(1, ("File inode")); - tmp_inode->i_op = &cifs_file_inode_ops; - - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_direct_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_ops; - - if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && - (cifs_sb->tcon->ses->server->maxBuf < - PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) - tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; - else - tmp_inode->i_data.a_ops = &cifs_addr_ops; - - if (isNewInode) - return; /* No sense invalidating pages for new inode - since we have not started caching readahead - file data for it yet */ - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } - } else if (S_ISDIR(tmp_inode->i_mode)) { - cFYI(1, ("Directory inode")); - tmp_inode->i_op = &cifs_dir_inode_ops; - tmp_inode->i_fop = &cifs_dir_ops; - } else if (S_ISLNK(tmp_inode->i_mode)) { - cFYI(1, ("Symbolic Link inode")); - tmp_inode->i_op = &cifs_symlink_inode_ops; -/* tmp_inode->i_fop = *//* do not need to set to anything */ - } else { - cFYI(1, ("Special inode")); - init_special_inode(tmp_inode, tmp_inode->i_mode, - tmp_inode->i_rdev); - } -} - /* BB eventually need to add the following helper function to resolve NT_STATUS_STOPPED_ON_SYMLINK return code when we try to do FindFirst on (NTFS) directory symlinks */ @@ -872,7 +786,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, len = strnlen(filename, PATH_MAX); } - *pinum = le64_to_cpu(pFindData->UniqueId); + *pinum = le64_to_cpu(pFindData->basic.UniqueId); } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { FILE_DIRECTORY_INFO *pFindData = (FILE_DIRECTORY_INFO *)current_entry; @@ -934,9 +848,11 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, struct cifsFileInfo *pCifsF; unsigned int obj_type; __u64 inum; + ino_t ino; struct cifs_sb_info *cifs_sb; struct inode *tmp_inode; struct dentry *tmp_dentry; + struct cifs_fattr fattr; /* get filename and len into qstring */ /* get dentry */ @@ -967,39 +883,49 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, return rc; /* only these two infolevels return valid inode numbers */ - if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || - pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, - &inum); - else - rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, - NULL); + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { + cifs_unix_basic_to_fattr(&fattr, + &((FILE_UNIX_INFO *) pfindEntry)->basic, + cifs_sb); + tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, + &fattr); + obj_type = fattr.cf_dtype; + ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); + } else { + if (pCifsF->srch_inf.info_level == + SMB_FIND_FILE_ID_FULL_DIR_INFO) + rc = construct_dentry(&qstring, file, &tmp_inode, + &tmp_dentry, &inum); + else + rc = construct_dentry(&qstring, file, &tmp_inode, + &tmp_dentry, NULL); - if ((tmp_inode == NULL) || (tmp_dentry == NULL)) - return -ENOMEM; + if ((tmp_inode == NULL) || (tmp_dentry == NULL)) { + rc = -ENOMEM; + goto out; + } - /* we pass in rc below, indicating whether it is a new inode, - so we can figure out whether to invalidate the inode cached - data if the file has changed */ - if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) - unix_fill_in_inode(tmp_inode, - (FILE_UNIX_INFO *)pfindEntry, - &obj_type, rc); - else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) - fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, - pfindEntry, &obj_type, rc); - else - fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); + /* we pass in rc below, indicating whether it is a new inode, + * so we can figure out whether to invalidate the inode cached + * data if the file has changed + */ + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) + fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc); + else + fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc); - if (rc) /* new inode - needs to be tied to dentry */ { - d_instantiate(tmp_dentry, tmp_inode); - if (rc == 2) - d_rehash(tmp_dentry); - } + /* new inode - needs to be tied to dentry */ + if (rc) { + d_instantiate(tmp_dentry, tmp_inode); + if (rc == 2) + d_rehash(tmp_dentry); + } + ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); + } rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, - tmp_inode->i_ino, obj_type); + ino, obj_type); if (rc) { cFYI(1, ("filldir rc = %d", rc)); /* we can not return filldir errors to the caller @@ -1008,6 +934,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, rc = -EOVERFLOW; } +out: dput(tmp_dentry); return rc; } -- GitLab From 956dba3caaf66b84fe5f6180e0e4dd03902c7980 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft <apw@canonical.com> Date: Wed, 1 Jul 2009 15:20:59 +0100 Subject: [PATCH 0529/1002] drm/i915: fix up a raw 64bit divide We are seeing compilation failures on i386 in some environments due to an undefined reference as below: ERROR: "__udivdi3" [drivers/gpu/drm/i915/i915.ko] undefined! This is generated due to a raw 64 bit divide in the i915 driver. Fix up this raw divide. Signed-off-by: Andy Whitcroft <apw@canonical.com> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a84ac05ef0483..59de4951b6eec 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1577,7 +1577,7 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes, temp = (u64) DATA_N * pixel_clock; temp = div_u64(temp, link_clock); - m_n->gmch_m = (temp * bytes_per_pixel) / nlanes; + m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes); m_n->gmch_n = DATA_N; fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); -- GitLab From 1ae8c0a56eeb3ed358b78ccadd024d6b721f26bc Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 28 Jun 2009 15:42:17 -0700 Subject: [PATCH 0530/1002] drm/i915: Make driver less chatty Convert many printk calls to DRM_DEBUG calls to reduce kernel log noise for normal activities. Switch other printk calls to DRM_ERROR or DRM_INFO. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++---- drivers/gpu/drm/i915/intel_dp_i2c.c | 11 ++++++----- drivers/gpu/drm/i915/intel_fb.c | 18 +++++++++--------- drivers/gpu/drm/i915/intel_lvds.c | 4 ++-- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6096600aff607..0e704bb26e99d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -846,7 +846,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, return 0; } - printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); + DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr); dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e3cb4025e323c..aef2a261a8374 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -57,8 +57,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) struct drm_i915_private *dev_priv = dev->dev_private; if (!dev || !dev_priv) { - printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv); - printk(KERN_ERR "DRM not initialized, aborting suspend.\n"); + DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv); + DRM_ERROR("DRM not initialized, aborting suspend.\n"); return -ENODEV; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8f8d37d5663a0..6770ae88370d6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -246,7 +246,7 @@ intel_dp_aux_ch(struct intel_output *intel_output, } if ((status & DP_AUX_CH_CTL_DONE) == 0) { - printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); + DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); return -EBUSY; } @@ -254,11 +254,14 @@ intel_dp_aux_ch(struct intel_output *intel_output, * Timeouts occur when the sink is not connected */ if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { - printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status); + DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); return -EIO; } + + /* Timeouts occur when the device isn't connected, so they're + * "normal" -- don't fill the kernel log with these */ if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { - printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status); + DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status); return -ETIMEDOUT; } @@ -411,7 +414,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, dp_priv->link_bw = bws[clock]; dp_priv->lane_count = lane_count; adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); - printk(KERN_ERR "link bw %02x lane count %d clock %d\n", + DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n", dp_priv->link_bw, dp_priv->lane_count, adjusted_mode->clock); return true; diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c index 4e60f14b1a6db..a63b6f57d2d4e 100644 --- a/drivers/gpu/drm/i915/intel_dp_i2c.c +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c @@ -29,6 +29,7 @@ #include <linux/sched.h> #include <linux/i2c.h> #include "intel_dp.h" +#include "drmP.h" /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ @@ -84,7 +85,7 @@ i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, msg, msg_bytes, reply, reply_bytes); if (ret < 0) { - printk(KERN_ERR "aux_ch failed %d\n", ret); + DRM_DEBUG("aux_ch failed %d\n", ret); return ret; } switch (reply[0] & AUX_I2C_REPLY_MASK) { @@ -94,14 +95,14 @@ i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, } return reply_bytes - 1; case AUX_I2C_REPLY_NACK: - printk(KERN_ERR "aux_ch nack\n"); + DRM_DEBUG("aux_ch nack\n"); return -EREMOTEIO; case AUX_I2C_REPLY_DEFER: - printk(KERN_ERR "aux_ch defer\n"); + DRM_DEBUG("aux_ch defer\n"); udelay(100); break; default: - printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]); + DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]); return -EREMOTEIO; } } @@ -223,7 +224,7 @@ i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, if (ret >= 0) ret = num; i2c_algo_dp_aux_stop(adapter, reading); - printk(KERN_ERR "dp_aux_xfer return %d\n", ret); + DRM_DEBUG("dp_aux_xfer return %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 1af7d68e38075..1d30802e773e3 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -453,7 +453,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, size = ALIGN(size, PAGE_SIZE); fbo = drm_gem_object_alloc(dev, size); if (!fbo) { - printk(KERN_ERR "failed to allocate framebuffer\n"); + DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } @@ -610,8 +610,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, par->dev = dev; /* To allow resizeing without swapping buffers */ - printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, - intel_fb->base.height, obj_priv->gtt_offset, fbo); + DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width, + intel_fb->base.height, obj_priv->gtt_offset, fbo); mutex_unlock(&dev->struct_mutex); return 0; @@ -698,13 +698,13 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc * } else intelfb_set_par(info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + DRM_INFO("fb%d: %s frame buffer device\n", info->node, info->fix.id); /* Switch back to kernel console on panic */ kernelfb_mode = *modeset; atomic_notifier_chain_register(&panic_notifier_list, &paniced); - printk(KERN_INFO "registered panic notifier\n"); + DRM_DEBUG("registered panic notifier\n"); return 0; } @@ -852,13 +852,13 @@ static int intelfb_single_fb_probe(struct drm_device *dev) } else intelfb_set_par(info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, + DRM_INFO("fb%d: %s frame buffer device\n", info->node, info->fix.id); /* Switch back to kernel console on panic */ kernelfb_mode = *modeset; atomic_notifier_chain_register(&panic_notifier_list, &paniced); - printk(KERN_INFO "registered panic notifier\n"); + DRM_DEBUG("registered panic notifier\n"); return 0; } @@ -872,8 +872,8 @@ void intelfb_restore(void) { int ret; if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) { - printk(KERN_ERR "Failed to restore crtc configuration: %d\n", - ret); + DRM_ERROR("Failed to restore crtc configuration: %d\n", + ret); } } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 9564ca44a977e..f65044b1647b2 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -252,14 +252,14 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, /* Should never happen!! */ if (!IS_I965G(dev) && intel_crtc->pipe == 0) { - printk(KERN_ERR "Can't support LVDS on pipe A\n"); + DRM_ERROR("Can't support LVDS on pipe A\n"); return false; } /* Should never happen!! */ list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { - printk(KERN_ERR "Can't enable LVDS and another " + DRM_ERROR("Can't enable LVDS and another " "encoder on the same pipe\n"); return false; } -- GitLab From 00460f41fffc0435dbb6ab4b058a190163d57ce6 Mon Sep 17 00:00:00 2001 From: David Howells <dhowells@redhat.com> Date: Thu, 2 Jul 2009 00:46:16 +0100 Subject: [PATCH 0531/1002] FRV: Implement atomic64_t Implement atomic64_t and its ops for FRV. Tested with the following patch: diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 55e4fab..086d50d 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -746,6 +746,52 @@ static void __init parse_cmdline_early(char *cmdline) } /* end parse_cmdline_early() */ +static atomic64_t xxx; + +static void test_atomic64(void) +{ + atomic64_set(&xxx, 0x12300000023LL); + + mb(); + BUG_ON(atomic64_read(&xxx) != 0x12300000023LL); + mb(); + if (atomic64_inc_return(&xxx) != 0x12300000024LL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != 0x12300000024LL); + mb(); + if (atomic64_sub_return(0x36900000050LL, &xxx) != -0x2460000002cLL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != -0x2460000002cLL); + mb(); + if (atomic64_dec_return(&xxx) != -0x2460000002dLL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != -0x2460000002dLL); + mb(); + if (atomic64_add_return(0x36800000001LL, &xxx) != 0x121ffffffd4LL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != 0x121ffffffd4LL); + mb(); + if (atomic64_cmpxchg(&xxx, 0x123456789abcdefLL, 0x121ffffffd4LL) != 0x121ffffffd4LL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != 0x121ffffffd4LL); + mb(); + if (atomic64_cmpxchg(&xxx, 0x121ffffffd4LL, 0x123456789abcdefLL) != 0x121ffffffd4LL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != 0x123456789abcdefLL); + mb(); + if (atomic64_xchg(&xxx, 0xabcdef123456789LL) != 0x123456789abcdefLL) + BUG(); + mb(); + BUG_ON(atomic64_read(&xxx) != 0xabcdef123456789LL); + mb(); +} + /*****************************************************************************/ /* * @@ -845,6 +891,8 @@ void __init setup_arch(char **cmdline_p) // asm volatile("movgs %0,timerd" :: "r"(10000000)); // __set_HSR(0, __get_HSR(0) | HSR0_ETMD); + test_atomic64(); + } /* end setup_arch() */ #if 0 Note that this doesn't cover all the trivial wrappers, but does cover all the substantial implementations. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/frv/include/asm/atomic.h | 68 +++++++++++++- arch/frv/include/asm/system.h | 2 + arch/frv/kernel/frv_ksyms.c | 4 + arch/frv/lib/Makefile | 2 +- arch/frv/lib/atomic-ops.S | 3 +- arch/frv/lib/atomic64-ops.S | 162 ++++++++++++++++++++++++++++++++++ 6 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 arch/frv/lib/atomic64-ops.S diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h index 0409d981fd395..00a57af79afc6 100644 --- a/arch/frv/include/asm/atomic.h +++ b/arch/frv/include/asm/atomic.h @@ -121,10 +121,72 @@ static inline void atomic_dec(atomic_t *v) #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) #define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) +/* + * 64-bit atomic ops + */ +typedef struct { + volatile long long counter; +} atomic64_t; + +#define ATOMIC64_INIT(i) { (i) } + +static inline long long atomic64_read(atomic64_t *v) +{ + long long counter; + + asm("ldd%I1 %M1,%0" + : "=e"(counter) + : "m"(v->counter)); + return counter; +} + +static inline void atomic64_set(atomic64_t *v, long long i) +{ + asm volatile("std%I0 %1,%M0" + : "=m"(v->counter) + : "e"(i)); +} + +extern long long atomic64_inc_return(atomic64_t *v); +extern long long atomic64_dec_return(atomic64_t *v); +extern long long atomic64_add_return(long long i, atomic64_t *v); +extern long long atomic64_sub_return(long long i, atomic64_t *v); + +static inline long long atomic64_add_negative(long long i, atomic64_t *v) +{ + return atomic64_add_return(i, v) < 0; +} + +static inline void atomic64_add(long long i, atomic64_t *v) +{ + atomic64_add_return(i, v); +} + +static inline void atomic64_sub(long long i, atomic64_t *v) +{ + atomic64_sub_return(i, v); +} + +static inline void atomic64_inc(atomic64_t *v) +{ + atomic64_inc_return(v); +} + +static inline void atomic64_dec(atomic64_t *v) +{ + atomic64_dec_return(v); +} + +#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0) +#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) +#define atomic64_inc_and_test(v) (atomic64_inc_return((v)) == 0) + /*****************************************************************************/ /* * exchange value with memory */ +extern uint64_t __xchg_64(uint64_t i, volatile void *v); + #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS #define xchg(ptr, x) \ @@ -174,8 +236,10 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v); #define tas(ptr) (xchg((ptr), 1)) -#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) +#define atomic_cmpxchg(v, old, new) (cmpxchg(&(v)->counter, old, new)) +#define atomic_xchg(v, new) (xchg(&(v)->counter, new)) +#define atomic64_cmpxchg(v, old, new) (__cmpxchg_64(old, new, &(v)->counter)) +#define atomic64_xchg(v, new) (__xchg_64(new, &(v)->counter)) static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) { diff --git a/arch/frv/include/asm/system.h b/arch/frv/include/asm/system.h index 7742ec000cc47..efd22d9077ac3 100644 --- a/arch/frv/include/asm/system.h +++ b/arch/frv/include/asm/system.h @@ -208,6 +208,8 @@ extern void free_initmem(void); * - if (*ptr == test) then orig = *ptr; *ptr = test; * - if (*ptr != test) then orig = *ptr; */ +extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v); + #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS #define cmpxchg(ptr, test, new) \ diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 0316b3c50efff..a89803b58b9a9 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -67,6 +67,10 @@ EXPORT_SYMBOL(atomic_sub_return); EXPORT_SYMBOL(__xchg_32); EXPORT_SYMBOL(__cmpxchg_32); #endif +EXPORT_SYMBOL(atomic64_add_return); +EXPORT_SYMBOL(atomic64_sub_return); +EXPORT_SYMBOL(__xchg_64); +EXPORT_SYMBOL(__cmpxchg_64); EXPORT_SYMBOL(__debug_bug_printk); EXPORT_SYMBOL(__delay_loops_MHz); diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile index 08be305c9f446..4ff2fb1e6b169 100644 --- a/arch/frv/lib/Makefile +++ b/arch/frv/lib/Makefile @@ -4,5 +4,5 @@ lib-y := \ __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \ - checksum.o memcpy.o memset.o atomic-ops.o \ + checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \ outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S index ee0ac905fb08a..5e9e6ab5dd0e8 100644 --- a/arch/frv/lib/atomic-ops.S +++ b/arch/frv/lib/atomic-ops.S @@ -163,11 +163,10 @@ __cmpxchg_32: ld.p @(gr11,gr0),gr8 orcr cc7,cc7,cc3 subcc gr8,gr9,gr7,icc0 - bne icc0,#0,1f + bnelr icc0,#0 cst.p gr10,@(gr11,gr0) ,cc3,#1 corcc gr29,gr29,gr0 ,cc3,#1 beq icc3,#0,0b -1: bralr .size __cmpxchg_32, .-__cmpxchg_32 diff --git a/arch/frv/lib/atomic64-ops.S b/arch/frv/lib/atomic64-ops.S new file mode 100644 index 0000000000000..b6194eeac127e --- /dev/null +++ b/arch/frv/lib/atomic64-ops.S @@ -0,0 +1,162 @@ +/* kernel atomic64 operations + * + * For an explanation of how atomic ops work in this arch, see: + * Documentation/frv/atomic-ops.txt + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/spr-regs.h> + + .text + .balign 4 + + +############################################################################### +# +# long long atomic64_inc_return(atomic64_t *v) +# +############################################################################### + .globl atomic64_inc_return + .type atomic64_inc_return,@function +atomic64_inc_return: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + addicc gr9,#1,gr9,icc0 + addxi gr8,#0,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_inc_return, .-atomic64_inc_return + +############################################################################### +# +# long long atomic64_dec_return(atomic64_t *v) +# +############################################################################### + .globl atomic64_dec_return + .type atomic64_dec_return,@function +atomic64_dec_return: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + subicc gr9,#1,gr9,icc0 + subxi gr8,#0,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_dec_return, .-atomic64_dec_return + +############################################################################### +# +# long long atomic64_add_return(long long i, atomic64_t *v) +# +############################################################################### + .globl atomic64_add_return + .type atomic64_add_return,@function +atomic64_add_return: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + addcc gr9,gr5,gr9,icc0 + addx gr8,gr4,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_add_return, .-atomic64_add_return + +############################################################################### +# +# long long atomic64_sub_return(long long i, atomic64_t *v) +# +############################################################################### + .globl atomic64_sub_return + .type atomic64_sub_return,@function +atomic64_sub_return: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + subcc gr9,gr5,gr9,icc0 + subx gr8,gr4,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_sub_return, .-atomic64_sub_return + +############################################################################### +# +# uint64_t __xchg_64(uint64_t i, uint64_t *v) +# +############################################################################### + .globl __xchg_64 + .type __xchg_64,@function +__xchg_64: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + cstd.p gr4,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __xchg_64, .-__xchg_64 + +############################################################################### +# +# uint64_t __cmpxchg_64(uint64_t test, uint64_t new, uint64_t *v) +# +############################################################################### + .globl __cmpxchg_64 + .type __cmpxchg_64,@function +__cmpxchg_64: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr12,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 + subcc gr8,gr4,gr0,icc0 + subcc.p gr9,gr5,gr0,icc1 + bnelr icc0,#0 + bnelr icc1,#0 + cstd.p gr10,@(gr12,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __cmpxchg_64, .-__cmpxchg_64 + -- GitLab From 42ca4fb69126dd9d0e25112edca1cacf846aa5c3 Mon Sep 17 00:00:00 2001 From: David Howells <dhowells@redhat.com> Date: Thu, 2 Jul 2009 00:46:21 +0100 Subject: [PATCH 0532/1002] FRV: Add basic performance counter support Add basic performance counter support to the FRV arch. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/frv/Kconfig | 1 + arch/frv/include/asm/perf_counter.h | 17 +++++++++++++++++ arch/frv/lib/Makefile | 2 +- arch/frv/lib/perf_counter.c | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 arch/frv/include/asm/perf_counter.h create mode 100644 arch/frv/lib/perf_counter.c diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index 8a5bd7a9c6f53..b86e19c9b5b0a 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -7,6 +7,7 @@ config FRV default y select HAVE_IDE select HAVE_ARCH_TRACEHOOK + select HAVE_PERF_COUNTERS config ZONE_DMA bool diff --git a/arch/frv/include/asm/perf_counter.h b/arch/frv/include/asm/perf_counter.h new file mode 100644 index 0000000000000..ccf726e61b2e3 --- /dev/null +++ b/arch/frv/include/asm/perf_counter.h @@ -0,0 +1,17 @@ +/* FRV performance counter support + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_PERF_COUNTER_H +#define _ASM_PERF_COUNTER_H + +#define PERF_COUNTER_INDEX_OFFSET 0 + +#endif /* _ASM_PERF_COUNTER_H */ diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile index 4ff2fb1e6b169..0a377210c89b3 100644 --- a/arch/frv/lib/Makefile +++ b/arch/frv/lib/Makefile @@ -5,4 +5,4 @@ lib-y := \ __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \ checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \ - outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o + outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_counter.o diff --git a/arch/frv/lib/perf_counter.c b/arch/frv/lib/perf_counter.c new file mode 100644 index 0000000000000..2000feecd5717 --- /dev/null +++ b/arch/frv/lib/perf_counter.c @@ -0,0 +1,19 @@ +/* Performance counter handling + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include <linux/perf_counter.h> + +/* + * mark the performance counter as pending + */ +void set_perf_counter_pending(void) +{ +} -- GitLab From 9974f496782b7612e36a143bedda858f1cb953d4 Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Thu, 2 Jul 2009 08:05:58 +0200 Subject: [PATCH 0533/1002] perf_counter tools: Make symbol loading consistently return number of loaded symbols perf_counter tools: Make symbol loading consistently return number of loaded symbols. Signed-off-by: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246514758.13293.42.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/symbol.c | 9 ++++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 132de8b28dbb0..3becc8a35bee1 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -172,7 +172,7 @@ static int load_kernel(void) return -1; err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); - if (err) { + if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; } else diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index be1b7584796dd..58d1612894ffa 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -189,7 +189,7 @@ static int load_kernel(void) return -1; err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); - if (err) { + if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; } else diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cdc74cfb15178..97fde1d843655 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -364,7 +364,7 @@ static int parse_symbols(void) if (kernel_dso == NULL) return -1; - if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) + if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) <= 0) goto out_delete_dso; node = rb_first(&kernel_dso->syms); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 78c2efde01b7b..c077b6a146904 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -146,6 +146,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb char *line = NULL; size_t n; FILE *file = fopen("/proc/kallsyms", "r"); + int count = 0; if (file == NULL) goto out_failure; @@ -188,8 +189,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb if (filter && filter(self, sym)) symbol__delete(sym, self->sym_priv_size); - else + else { dso__insert_symbol(self, sym); + count++; + } } /* @@ -212,7 +215,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb free(line); fclose(file); - return 0; + return count; out_delete_line: free(line); @@ -639,7 +642,7 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, if (vmlinux) err = dso__load_vmlinux(self, vmlinux, filter, verbose); - if (err < 0) + if (err <= 0) err = dso__load_kallsyms(self, filter, verbose); return err; -- GitLab From 208b4b4a59351011b7f212e273f2b7bc47a9c482 Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Thu, 2 Jul 2009 08:07:10 +0200 Subject: [PATCH 0534/1002] perf_counter tools: Add infrastructure to support loading of kernel module symbols Add infrastructure for module path discovery and section load addresses. Signed-off-by: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246514830.13293.44.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/Makefile | 2 + tools/perf/util/module.c | 509 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/module.h | 53 ++++ 3 files changed, 564 insertions(+) create mode 100644 tools/perf/util/module.c create mode 100644 tools/perf/util/module.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 8f7fd1b050a57..7822b3d6baca2 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -306,6 +306,7 @@ LIB_H += util/strlist.h LIB_H += util/run-command.h LIB_H += util/sigchain.h LIB_H += util/symbol.h +LIB_H += util/module.h LIB_H += util/color.h LIB_OBJS += util/abspath.o @@ -329,6 +330,7 @@ LIB_OBJS += util/usage.o LIB_OBJS += util/wrapper.o LIB_OBJS += util/sigchain.o LIB_OBJS += util/symbol.o +LIB_OBJS += util/module.o LIB_OBJS += util/color.o LIB_OBJS += util/pager.o LIB_OBJS += util/header.o diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c new file mode 100644 index 0000000000000..ddabe925d65dc --- /dev/null +++ b/tools/perf/util/module.c @@ -0,0 +1,509 @@ +#include "util.h" +#include "../perf.h" +#include "string.h" +#include "module.h" + +#include <libelf.h> +#include <gelf.h> +#include <elf.h> +#include <dirent.h> +#include <sys/utsname.h> + +static unsigned int crc32(const char *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} + +/* module section methods */ + +struct sec_dso *sec_dso__new_dso(const char *name) +{ + struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1); + + if (self != NULL) { + strcpy(self->name, name); + self->secs = RB_ROOT; + self->find_section = sec_dso__find_section; + } + + return self; +} + +static void sec_dso__delete_section(struct section *self) +{ + free(((void *)self)); +} + +void sec_dso__delete_sections(struct sec_dso *self) +{ + struct section *pos; + struct rb_node *next = rb_first(&self->secs); + + while (next) { + pos = rb_entry(next, struct section, rb_node); + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, &self->secs); + sec_dso__delete_section(pos); + } +} + +void sec_dso__delete_self(struct sec_dso *self) +{ + sec_dso__delete_sections(self); + free(self); +} + +static void sec_dso__insert_section(struct sec_dso *self, struct section *sec) +{ + struct rb_node **p = &self->secs.rb_node; + struct rb_node *parent = NULL; + const u64 hash = sec->hash; + struct section *s; + + while (*p != NULL) { + parent = *p; + s = rb_entry(parent, struct section, rb_node); + if (hash < s->hash) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&sec->rb_node, parent, p); + rb_insert_color(&sec->rb_node, &self->secs); +} + +struct section *sec_dso__find_section(struct sec_dso *self, const char *name) +{ + struct rb_node *n; + u64 hash; + int len; + + if (self == NULL) + return NULL; + + len = strlen(name); + hash = crc32(name, len); + + n = self->secs.rb_node; + + while (n) { + struct section *s = rb_entry(n, struct section, rb_node); + + if (hash < s->hash) + n = n->rb_left; + else if (hash > s->hash) + n = n->rb_right; + else { + if (!strcmp(name, s->name)) + return s; + else + n = rb_next(&s->rb_node); + } + } + + return NULL; +} + +static size_t sec_dso__fprintf_section(struct section *self, FILE *fp) +{ + return fprintf(fp, "name:%s vma:%llx path:%s\n", + self->name, self->vma, self->path); +} + +size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp) +{ + size_t ret = fprintf(fp, "dso: %s\n", self->name); + + struct rb_node *nd; + for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) { + struct section *pos = rb_entry(nd, struct section, rb_node); + ret += sec_dso__fprintf_section(pos, fp); + } + + return ret; +} + +static struct section *section__new(const char *name, const char *path) +{ + struct section *self = calloc(1, sizeof(*self)); + + if (!self) + goto out_failure; + + self->name = calloc(1, strlen(name) + 1); + if (!self->name) + goto out_failure; + + self->path = calloc(1, strlen(path) + 1); + if (!self->path) + goto out_failure; + + strcpy(self->name, name); + strcpy(self->path, path); + self->hash = crc32(self->name, strlen(name)); + + return self; + +out_failure: + if (self) { + if (self->name) + free(self->name); + if (self->path) + free(self->path); + free(self); + } + + return NULL; +} + +/* module methods */ + +struct mod_dso *mod_dso__new_dso(const char *name) +{ + struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1); + + if (self != NULL) { + strcpy(self->name, name); + self->mods = RB_ROOT; + self->find_module = mod_dso__find_module; + } + + return self; +} + +static void mod_dso__delete_module(struct module *self) +{ + free(((void *)self)); +} + +void mod_dso__delete_modules(struct mod_dso *self) +{ + struct module *pos; + struct rb_node *next = rb_first(&self->mods); + + while (next) { + pos = rb_entry(next, struct module, rb_node); + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, &self->mods); + mod_dso__delete_module(pos); + } +} + +void mod_dso__delete_self(struct mod_dso *self) +{ + mod_dso__delete_modules(self); + free(self); +} + +static void mod_dso__insert_module(struct mod_dso *self, struct module *mod) +{ + struct rb_node **p = &self->mods.rb_node; + struct rb_node *parent = NULL; + const u64 hash = mod->hash; + struct module *m; + + while (*p != NULL) { + parent = *p; + m = rb_entry(parent, struct module, rb_node); + if (hash < m->hash) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + rb_link_node(&mod->rb_node, parent, p); + rb_insert_color(&mod->rb_node, &self->mods); +} + +struct module *mod_dso__find_module(struct mod_dso *self, const char *name) +{ + struct rb_node *n; + u64 hash; + int len; + + if (self == NULL) + return NULL; + + len = strlen(name); + hash = crc32(name, len); + + n = self->mods.rb_node; + + while (n) { + struct module *m = rb_entry(n, struct module, rb_node); + + if (hash < m->hash) + n = n->rb_left; + else if (hash > m->hash) + n = n->rb_right; + else { + if (!strcmp(name, m->name)) + return m; + else + n = rb_next(&m->rb_node); + } + } + + return NULL; +} + +static size_t mod_dso__fprintf_module(struct module *self, FILE *fp) +{ + return fprintf(fp, "name:%s path:%s\n", self->name, self->path); +} + +size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp) +{ + struct rb_node *nd; + size_t ret; + + ret = fprintf(fp, "dso: %s\n", self->name); + + for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) { + struct module *pos = rb_entry(nd, struct module, rb_node); + + ret += mod_dso__fprintf_module(pos, fp); + } + + return ret; +} + +static struct module *module__new(const char *name, const char *path) +{ + struct module *self = calloc(1, sizeof(*self)); + + if (!self) + goto out_failure; + + self->name = calloc(1, strlen(name) + 1); + if (!self->name) + goto out_failure; + + self->path = calloc(1, strlen(path) + 1); + if (!self->path) + goto out_failure; + + strcpy(self->name, name); + strcpy(self->path, path); + self->hash = crc32(self->name, strlen(name)); + + return self; + +out_failure: + if (self) { + if (self->name) + free(self->name); + if (self->path) + free(self->path); + free(self); + } + + return NULL; +} + +static int mod_dso__load_sections(struct module *mod) +{ + int count = 0, path_len; + struct dirent *entry; + char *line = NULL; + char *dir_path; + DIR *dir; + size_t n; + + path_len = strlen("/sys/module/"); + path_len += strlen(mod->name); + path_len += strlen("/sections/"); + + dir_path = calloc(1, path_len + 1); + if (dir_path == NULL) + goto out_failure; + + strcat(dir_path, "/sys/module/"); + strcat(dir_path, mod->name); + strcat(dir_path, "/sections/"); + + dir = opendir(dir_path); + if (dir == NULL) + goto out_free; + + while ((entry = readdir(dir))) { + struct section *section; + char *path, *vma; + int line_len; + FILE *file; + + if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) + continue; + + path = calloc(1, path_len + strlen(entry->d_name) + 1); + if (path == NULL) + break; + strcat(path, dir_path); + strcat(path, entry->d_name); + + file = fopen(path, "r"); + if (file == NULL) { + free(path); + break; + } + + line_len = getline(&line, &n, file); + if (line_len < 0) { + free(path); + fclose(file); + break; + } + + if (!line) { + free(path); + fclose(file); + break; + } + + line[--line_len] = '\0'; /* \n */ + + vma = strstr(line, "0x"); + if (!vma) { + free(path); + fclose(file); + break; + } + vma += 2; + + section = section__new(entry->d_name, path); + if (!section) { + fprintf(stderr, "load_sections: allocation error\n"); + free(path); + fclose(file); + break; + } + + hex2u64(vma, §ion->vma); + sec_dso__insert_section(mod->sections, section); + + free(path); + fclose(file); + count++; + } + + closedir(dir); + free(line); + free(dir_path); + + return count; + +out_free: + free(dir_path); + +out_failure: + return count; +} + +static int mod_dso__load_module_paths(struct mod_dso *self) +{ + struct utsname uts; + int count = 0, len; + char *line = NULL; + FILE *file; + char *path; + size_t n; + + if (uname(&uts) < 0) + goto out_failure; + + len = strlen("/lib/modules/"); + len += strlen(uts.release); + len += strlen("/modules.dep"); + + path = calloc(1, len); + if (path == NULL) + goto out_failure; + + strcat(path, "/lib/modules/"); + strcat(path, uts.release); + strcat(path, "/modules.dep"); + + file = fopen(path, "r"); + free(path); + if (file == NULL) + goto out_failure; + + while (!feof(file)) { + char *path, *name, *tmp; + struct module *module; + int line_len, len; + + line_len = getline(&line, &n, file); + if (line_len < 0) + break; + + if (!line) + goto out_failure; + + line[--line_len] = '\0'; /* \n */ + + path = strtok(line, ":"); + if (!path) + goto out_failure; + + name = strdup(path); + name = strtok(name, "/"); + + tmp = name; + + while (tmp) { + tmp = strtok(NULL, "/"); + if (tmp) + name = tmp; + } + name = strsep(&name, "."); + + /* Quirk: replace '-' with '_' in sound modules */ + for (len = strlen(name); len; len--) { + if (*(name+len) == '-') + *(name+len) = '_'; + } + + module = module__new(name, path); + if (!module) { + fprintf(stderr, "load_module_paths: allocation error\n"); + goto out_failure; + } + mod_dso__insert_module(self, module); + + module->sections = sec_dso__new_dso("sections"); + if (!module->sections) { + fprintf(stderr, "load_module_paths: allocation error\n"); + goto out_failure; + } + + module->active = mod_dso__load_sections(module); + + if (module->active > 0) + count++; + } + + free(line); + fclose(file); + + return count; + +out_failure: + return -1; +} + +int mod_dso__load_modules(struct mod_dso *dso) +{ + int err; + + err = mod_dso__load_module_paths(dso); + + return err; +} diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h new file mode 100644 index 0000000000000..8a592ef641cae --- /dev/null +++ b/tools/perf/util/module.h @@ -0,0 +1,53 @@ +#ifndef _PERF_MODULE_ +#define _PERF_MODULE_ 1 + +#include <linux/types.h> +#include "../types.h" +#include <linux/list.h> +#include <linux/rbtree.h> + +struct section { + struct rb_node rb_node; + u64 hash; + u64 vma; + char *name; + char *path; +}; + +struct sec_dso { + struct list_head node; + struct rb_root secs; + struct section *(*find_section)(struct sec_dso *, const char *name); + char name[0]; +}; + +struct module { + struct rb_node rb_node; + u64 hash; + char *name; + char *path; + struct sec_dso *sections; + int active; +}; + +struct mod_dso { + struct list_head node; + struct rb_root mods; + struct module *(*find_module)(struct mod_dso *, const char *name); + char name[0]; +}; + +struct sec_dso *sec_dso__new_dso(const char *name); +void sec_dso__delete_sections(struct sec_dso *self); +void sec_dso__delete_self(struct sec_dso *self); +size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp); +struct section *sec_dso__find_section(struct sec_dso *self, const char *name); + +struct mod_dso *mod_dso__new_dso(const char *name); +void mod_dso__delete_modules(struct mod_dso *self); +void mod_dso__delete_self(struct mod_dso *self); +size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp); +struct module *mod_dso__find_module(struct mod_dso *self, const char *name); +int mod_dso__load_modules(struct mod_dso *dso); + +#endif /* _PERF_MODULE_ */ -- GitLab From 6cfcc53ed4f3ecb9319e73a03f34f1eddcb644dd Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Thu, 2 Jul 2009 08:08:36 +0200 Subject: [PATCH 0535/1002] perf_counter tools: Connect module support infrastructure to symbol loading infrastructure Signed-off-by: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246514916.13293.46.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/symbol.c | 159 +++++++++++++++++++++++++++++++--- tools/perf/util/symbol.h | 5 +- 5 files changed, 156 insertions(+), 14 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 3becc8a35bee1..88205686eb6e3 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -171,7 +171,7 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0); if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 58d1612894ffa..38d136fedfb90 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -188,7 +188,7 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0); if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 97fde1d843655..9bb25fc3d4cee 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -364,7 +364,7 @@ static int parse_symbols(void) if (kernel_dso == NULL) return -1; - if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) <= 0) + if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1, 0) <= 0) goto out_delete_dso; node = rb_first(&kernel_dso->syms); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c077b6a146904..98a13114de70e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -35,7 +35,7 @@ static struct symbol *symbol__new(u64 start, u64 len, self = ((void *)self) + priv_size; } self->start = start; - self->end = start + len - 1; + self->end = len ? start + len - 1 : start; memcpy(self->name, name, namelen); return self; @@ -48,8 +48,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size) static size_t symbol__fprintf(struct symbol *self, FILE *fp) { - return fprintf(fp, " %llx-%llx %s\n", + if (!self->module) + return fprintf(fp, " %llx-%llx %s\n", self->start, self->end, self->name); + else + return fprintf(fp, " %llx-%llx %s \t[%s]\n", + self->start, self->end, self->name, self->module->name); } struct dso *dso__new(const char *name, unsigned int sym_priv_size) @@ -310,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym) sym->st_size != 0; } +static inline int elf_sym__is_label(const GElf_Sym *sym) +{ + return elf_sym__type(sym) == STT_NOTYPE && + sym->st_name != 0 && + sym->st_shndx != SHN_UNDEF && + sym->st_shndx != SHN_ABS; +} + +static inline const char *elf_sec__name(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return secstrs->d_buf + shdr->sh_name; +} + +static inline int elf_sec__is_text(const GElf_Shdr *shdr, + const Elf_Data *secstrs) +{ + return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; +} + static inline const char *elf_sym__name(const GElf_Sym *sym, const Elf_Data *symstrs) { @@ -451,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, } static int dso__load_sym(struct dso *self, int fd, const char *name, - symbol_filter_t filter, int verbose) + symbol_filter_t filter, int verbose, struct module *mod) { - Elf_Data *symstrs; + Elf_Data *symstrs, *secstrs; uint32_t nr_syms; int err = -1; uint32_t index; @@ -461,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, GElf_Shdr shdr; Elf_Data *syms; GElf_Sym sym; - Elf_Scn *sec, *sec_dynsym; + Elf_Scn *sec, *sec_dynsym, *sec_strndx; Elf *elf; size_t dynsym_idx; int nr = 0; @@ -520,6 +544,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, if (symstrs == NULL) goto out_elf_end; + sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); + if (sec_strndx == NULL) + goto out_elf_end; + + secstrs = elf_getdata(sec_strndx, NULL); + if (symstrs == NULL) + goto out_elf_end; + nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); @@ -529,8 +561,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { struct symbol *f; u64 obj_start; + struct section *section = NULL; + int is_label = elf_sym__is_label(&sym); + const char *section_name; - if (!elf_sym__is_function(&sym)) + if (!is_label && !elf_sym__is_function(&sym)) continue; sec = elf_getscn(elf, sym.st_shndx); @@ -538,6 +573,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, goto out_elf_end; gelf_getshdr(sec, &shdr); + + if (is_label && !elf_sec__is_text(&shdr, secstrs)) + continue; + + section_name = elf_sec__name(&shdr, secstrs); obj_start = sym.st_value; if (self->prelinked) { @@ -548,6 +588,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, sym.st_value -= shdr.sh_addr - shdr.sh_offset; } + if (mod) { + section = mod->sections->find_section(mod->sections, section_name); + if (section) + sym.st_value += section->vma; + else { + fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n", + mod->name, section_name); + goto out_elf_end; + } + } + f = symbol__new(sym.st_value, sym.st_size, elf_sym__name(&sym, symstrs), self->sym_priv_size, obj_start, verbose); @@ -557,6 +608,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, if (filter && filter(self, f)) symbol__delete(f, self->sym_priv_size); else { + f->module = mod; dso__insert_symbol(self, f); nr++; } @@ -606,7 +658,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) fd = open(name, O_RDONLY); } while (fd < 0); - ret = dso__load_sym(self, fd, name, filter, verbose); + ret = dso__load_sym(self, fd, name, filter, verbose, NULL); close(fd); /* @@ -620,6 +672,86 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) return ret; } +static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, + symbol_filter_t filter, int verbose) +{ + struct module *mod = mod_dso__find_module(mods, name); + int err = 0, fd; + + if (mod == NULL || !mod->active) + return err; + + fd = open(mod->path, O_RDONLY); + + if (fd < 0) + return err; + + err = dso__load_sym(self, fd, name, filter, verbose, mod); + close(fd); + + return err; +} + +int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) +{ + struct mod_dso *mods = mod_dso__new_dso("modules"); + struct module *pos; + struct rb_node *next; + int err; + + err = mod_dso__load_modules(mods); + + if (err <= 0) + return err; + + /* + * Iterate over modules, and load active symbols. + */ + next = rb_first(&mods->mods); + while (next) { + pos = rb_entry(next, struct module, rb_node); + err = dso__load_module(self, mods, pos->name, filter, verbose); + + if (err < 0) + break; + + next = rb_next(&pos->rb_node); + } + + if (err < 0) { + mod_dso__delete_modules(mods); + mod_dso__delete_self(mods); + } + + return err; +} + +static inline void dso__fill_symbol_holes(struct dso *self) +{ + struct symbol *prev = NULL; + struct rb_node *nd; + + for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { + struct symbol *pos = rb_entry(nd, struct symbol, rb_node); + + if (prev) { + u64 hole = 0; + int alias = pos->start == prev->start; + + if (!alias) + hole = prev->start - pos->end - 1; + + if (hole || alias) { + if (alias) + pos->end = prev->end; + else if (hole) + pos->end = prev->start - 1; + } + } + prev = pos; + } +} + static int dso__load_vmlinux(struct dso *self, const char *vmlinux, symbol_filter_t filter, int verbose) { @@ -628,19 +760,26 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux, if (fd < 0) return -1; - err = dso__load_sym(self, fd, vmlinux, filter, verbose); + err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); + + if (err > 0) + dso__fill_symbol_holes(self); + close(fd); return err; } int dso__load_kernel(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int verbose) + symbol_filter_t filter, int verbose, int modules) { int err = -1; - if (vmlinux) + if (vmlinux) { err = dso__load_vmlinux(self, vmlinux, filter, verbose); + if (err > 0 && modules) + err = dso__load_modules(self, filter, verbose); + } if (err <= 0) err = dso__load_kallsyms(self, filter, verbose); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 65a8449b91f52..4e141a30911e6 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -5,6 +5,7 @@ #include "types.h" #include <linux/list.h> #include <linux/rbtree.h> +#include "module.h" struct symbol { struct rb_node rb_node; @@ -13,6 +14,7 @@ struct symbol { u64 obj_start; u64 hist_sum; u64 *hist; + struct module *module; void *priv; char name[0]; }; @@ -41,7 +43,8 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym) struct symbol *dso__find_symbol(struct dso *self, u64 ip); int dso__load_kernel(struct dso *self, const char *vmlinux, - symbol_filter_t filter, int verbose); + symbol_filter_t filter, int verbose, int modules); +int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); int dso__load(struct dso *self, symbol_filter_t filter, int verbose); size_t dso__fprintf(struct dso *self, FILE *fp); -- GitLab From 429764873cf3fc3e73142872a674bb27cda589c1 Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Thu, 2 Jul 2009 08:09:46 +0200 Subject: [PATCH 0536/1002] perf_counter tools: Enable kernel module symbol loading in tools Add the -m/--modules option to perf report and perf annotate, which enables live module symbol/image loading. To be used with -k/--vmlinux. (Also give perf annotate a -P/--full-paths option.) Signed-off-by: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246514986.13293.48.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-annotate.c | 25 ++++++++++++++++++++----- tools/perf/builtin-report.c | 9 ++++++++- tools/perf/builtin-top.c | 12 ++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 88205686eb6e3..08ea6c5329d99 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -43,6 +43,10 @@ static int dump_trace = 0; static int verbose; +static int modules; + +static int full_paths; + static int print_line; static unsigned long page_size; @@ -171,7 +175,7 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0); + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; @@ -1268,19 +1272,25 @@ static void print_summary(char *filename) static void annotate_sym(struct dso *dso, struct symbol *sym) { - char *filename = dso->name; + char *filename = dso->name, *d_filename; u64 start, end, len; char command[PATH_MAX*2]; FILE *file; if (!filename) return; - if (dso == kernel_dso) + if (sym->module) + filename = sym->module->path; + else if (dso == kernel_dso) filename = vmlinux; start = sym->obj_start; if (!start) start = sym->start; + if (full_paths) + d_filename = filename; + else + d_filename = basename(filename); end = start + sym->end - sym->start + 1; len = sym->end - sym->start; @@ -1291,13 +1301,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) } printf("\n\n------------------------------------------------\n"); - printf(" Percent | Source code & Disassembly of %s\n", filename); + printf(" Percent | Source code & Disassembly of %s\n", d_filename); printf("------------------------------------------------\n"); if (verbose >= 2) printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); - sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); + sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", + (u64)start, (u64)end, filename, filename); if (verbose >= 3) printf("doing: %s\n", command); @@ -1472,8 +1483,12 @@ static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), + OPT_BOOLEAN('m', "modules", &modules, + "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_BOOLEAN('l', "print-line", &print_line, "print matching source lines (may be slow)"), + OPT_BOOLEAN('P', "full-paths", &full_paths, + "Don't shorten the displayed pathnames"), OPT_END() }; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 38d136fedfb90..b44476ca23988 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -46,6 +46,8 @@ static int dump_trace = 0; static int verbose; #define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) +static int modules; + static int full_paths; static unsigned long page_size; @@ -188,7 +190,7 @@ static int load_kernel(void) if (!kernel_dso) return -1; - err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0); + err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules); if (err <= 0) { dso__delete(kernel_dso); kernel_dso = NULL; @@ -648,6 +650,9 @@ sort__sym_print(FILE *fp, struct hist_entry *self) ret += fprintf(fp, "[%c] %s", self->dso == kernel_dso ? 'k' : self->dso == hypervisor_dso ? 'h' : '.', self->sym->name); + + if (self->sym->module) + ret += fprintf(fp, "\t[%s]", self->sym->module->name); } else { ret += fprintf(fp, "%#016llx", (u64)self->ip); } @@ -1710,6 +1715,8 @@ static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), + OPT_BOOLEAN('m', "modules", &modules, + "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): pid, comm, dso, symbol, parent"), OPT_BOOLEAN('P', "full-paths", &full_paths, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9bb25fc3d4cee..aa044ea1482bf 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -66,6 +66,7 @@ static unsigned int page_size; static unsigned int mmap_pages = 16; static int freq = 0; static int verbose = 0; +static char *vmlinux = NULL; static char *sym_filter; static unsigned long filter_start; @@ -265,7 +266,10 @@ static void print_sym_table(void) printf("%9.1f %10ld - ", syme->weight, syme->snap_count); color_fprintf(stdout, color, "%4.1f%%", pcnt); - printf(" - %016llx : %s\n", sym->start, sym->name); + printf(" - %016llx : %s", sym->start, sym->name); + if (sym->module) + printf("\t[%s]", sym->module->name); + printf("\n"); } } @@ -359,12 +363,13 @@ static int parse_symbols(void) { struct rb_node *node; struct symbol *sym; + int modules = vmlinux ? 1 : 0; kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); if (kernel_dso == NULL) return -1; - if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1, 0) <= 0) + if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0) goto out_delete_dso; node = rb_first(&kernel_dso->syms); @@ -680,6 +685,7 @@ static const struct option options[] = { "system-wide collection from all CPUs"), OPT_INTEGER('C', "CPU", &profile_cpu, "CPU to profile on"), + OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), OPT_INTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, @@ -709,6 +715,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) { int counter; + symbol__init(); + page_size = sysconf(_SC_PAGE_SIZE); argc = parse_options(argc, argv, options, top_usage, 0); -- GitLab From e1af3aec3e2e7d21d4b3054323779d478c19d907 Mon Sep 17 00:00:00 2001 From: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Date: Wed, 1 Jul 2009 16:50:25 +0800 Subject: [PATCH 0537/1002] tracing: Fix trace_print_seq() We will lose something if trace_seq->buffer[0] is 0, because the copy length is calculated by strlen() in seq_puts(), so using seq_write() instead of seq_puts(). There have a example: after reboot: # echo kmemtrace > current_tracer # echo 0 > options/kmem_minimalistic # cat trace # tracer: kmemtrace # # Nothing is exported, because the first byte of trace_seq->buffer[ ] is KMEMTRACE_USER_ALLOC. ( the value of KMEMTRACE_USER_ALLOC is zero, seeing kmemtrace_print_alloc_user() in kernel/trace/kmemtrace.c) Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> Acked-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <4A4B2351.5010300@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- kernel/trace/trace_output.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 7938f3ae93e3d..e0c2545622e8f 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -27,8 +27,7 @@ void trace_print_seq(struct seq_file *m, struct trace_seq *s) { int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; - s->buffer[len] = 0; - seq_puts(m, s->buffer); + seq_write(m, s->buffer, len); trace_seq_init(s); } -- GitLab From 251e1e44b97852aa5e53e71c4b47e55b2dfd054e Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Thu, 2 Jul 2009 08:54:01 +0200 Subject: [PATCH 0538/1002] x86: Fix printk call in print_local_apic() Instead of this: [ 75.690022] <7>printing local APIC contents on CPU#0/0: [ 75.704406] ... APIC ID: 00000000 (0) [ 75.707905] ... APIC VERSION: 00060015 [ 75.722551] ... APIC TASKPRI: 00000000 (00) [ 75.725473] ... APIC PROCPRI: 00000000 [ 75.728592] ... APIC LDR: 00000001 [ 75.742137] ... APIC SPIV: 000001ff [ 75.744101] ... APIC ISR field: [ 75.746648] 0123456789abcdef0123456789abcdef [ 75.746649] <7>00000000000000000000000000000000 Improve the code to be saner and simpler and just print out the bitfield in a single line using hexa values - not as a (rather pointless) binary bitfield. Partially reused Linus's initial fix for this. Reported-and-Tested-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <4A4C43BC.90506@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/apic/io_apic.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4d0216fcb36c4..8fd1efb5a0bd2 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1716,25 +1716,19 @@ __apicdebuginit(void) print_IO_APIC(void) return; } -__apicdebuginit(void) print_APIC_bitfield(int base) +__apicdebuginit(void) print_APIC_field(int base) { - unsigned int v; - int i, j; + int i; if (apic_verbosity == APIC_QUIET) return; - printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); - for (i = 0; i < 8; i++) { - v = apic_read(base + i*0x10); - for (j = 0; j < 32; j++) { - if (v & (1<<j)) - printk("1"); - else - printk("0"); - } - printk("\n"); - } + printk(KERN_DEBUG); + + for (i = 0; i < 8; i++) + printk(KERN_CONT "%08x", apic_read(base + i*0x10)); + + printk(KERN_CONT "\n"); } __apicdebuginit(void) print_local_APIC(void *dummy) @@ -1745,7 +1739,8 @@ __apicdebuginit(void) print_local_APIC(void *dummy) if (apic_verbosity == APIC_QUIET) return; - printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", + printk(KERN_DEBUG "\n"); + printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, read_apic_id()); @@ -1786,11 +1781,11 @@ __apicdebuginit(void) print_local_APIC(void *dummy) printk(KERN_DEBUG "... APIC SPIV: %08x\n", v); printk(KERN_DEBUG "... APIC ISR field:\n"); - print_APIC_bitfield(APIC_ISR); + print_APIC_field(APIC_ISR); printk(KERN_DEBUG "... APIC TMR field:\n"); - print_APIC_bitfield(APIC_TMR); + print_APIC_field(APIC_TMR); printk(KERN_DEBUG "... APIC IRR field:\n"); - print_APIC_bitfield(APIC_IRR); + print_APIC_field(APIC_IRR); if (APIC_INTEGRATED(ver)) { /* !82489DX */ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ -- GitLab From 826390796d09444b93e1f957582f8970ddfd9b3d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch <clemens@ladisch.de> Date: Thu, 2 Jul 2009 08:31:30 +0200 Subject: [PATCH 0539/1002] sound: virtuoso: fix Xonar D1/DX silence after resume When resuming, we better take the DACs out of the reset state before trying to use them. Reference: kernel bug #13599 http://bugzilla.kernel.org/show_bug.cgi?id=13599 Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Cc: <stable@kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/oxygen/virtuoso.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index bf971f7cfdc65..6ebcb6bdd7129 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c @@ -635,6 +635,8 @@ static void xonar_d2_resume(struct oxygen *chip) static void xonar_d1_resume(struct oxygen *chip) { + oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); + msleep(1); cs43xx_init(chip); xonar_enable_output(chip); } -- GitLab From 563c2bf59d392357bcc1d99642933cc88c687964 Mon Sep 17 00:00:00 2001 From: Daniel Mack <daniel@caiaq.de> Date: Thu, 2 Jul 2009 10:46:35 +0200 Subject: [PATCH 0540/1002] ALSA: snd_usb_caiaq: reparent sound device The sound device instance needs to be a child of the USB interface, not the USB device. Newer udev versions pay attention to that. Signed-off-by: Daniel Mack <daniel@caiaq.de> Reported-by: Lennart Poettering <lennart@poettering.net> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/usb/caiaq/device.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 0e5db719de244..de38108f0b283 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -35,7 +35,7 @@ #include "input.h" MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.17"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.18"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," @@ -349,7 +349,9 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) log("Unable to set up control system (ret=%d)\n", ret); } -static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) +static int create_card(struct usb_device *usb_dev, + struct usb_interface *intf, + struct snd_card **cardp) { int devnum; int err; @@ -374,7 +376,7 @@ static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct)); spin_lock_init(&dev->spinlock); - snd_card_set_dev(card, &usb_dev->dev); + snd_card_set_dev(card, &intf->dev); *cardp = card; return 0; @@ -461,7 +463,7 @@ static int __devinit snd_probe(struct usb_interface *intf, struct snd_card *card; struct usb_device *device = interface_to_usbdev(intf); - ret = create_card(device, &card); + ret = create_card(device, intf, &card); if (ret < 0) return ret; -- GitLab From 3f5d3465be8f6e04f43d9b6d543fe28d4be07d78 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 2 Jul 2009 11:51:44 +0200 Subject: [PATCH 0541/1002] ALSA: usx2y - reparent sound device Fix the parent device to be the USB interface, not the USB device. A similiar commit like 563c2bf59d392357bcc1d99642933cc88c687964. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/usb/usx2y/us122l.c | 2 +- sound/usb/usx2y/usbusx2y.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index a5aae9d67f317..fd44946ce4b3a 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -514,7 +514,6 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) US122L(card)->chip.dev->bus->busnum, US122L(card)->chip.dev->devnum ); - snd_card_set_dev(card, &device->dev); *cardp = card; return 0; } @@ -531,6 +530,7 @@ static int us122l_usb_probe(struct usb_interface *intf, if (err < 0) return err; + snd_card_set_dev(card, &intf->dev); if (!us122l_create_card(card)) { snd_card_free(card); return -EINVAL; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 5ce0da23ee96f..cb4bb8373ca29 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -364,7 +364,6 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp) 0,//us428(card)->usbmidi.ifnum, usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum ); - snd_card_set_dev(card, &device->dev); *cardp = card; return 0; } @@ -388,6 +387,7 @@ static int usX2Y_usb_probe(struct usb_device *device, err = usX2Y_create_card(device, &card); if (err < 0) return err; + snd_card_set_dev(card, &intf->dev); if ((err = usX2Y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); -- GitLab From 7a6a3a086fe60bb3b739f66e47dc5bbc8f530d32 Mon Sep 17 00:00:00 2001 From: Joerg Roedel <joerg.roedel@amd.com> Date: Thu, 2 Jul 2009 12:23:23 +0200 Subject: [PATCH 0542/1002] amd-iommu: handle alias entries correctly in init code An alias entry in the ACPI table means that the device can send requests to the IOMMU with both device ids, its own and the alias. This is not handled properly in the ACPI init code. This patch fixes the issue. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> --- arch/x86/kernel/amd_iommu_init.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 10b2accd12ea5..ec72c7779d6b3 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -691,6 +691,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; devid_to = e->ext >> 8; + set_dev_entry_from_acpi(iommu, devid , e->flags, 0); set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); amd_iommu_alias_table[devid] = devid_to; break; @@ -749,11 +750,13 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; for (dev_i = devid_start; dev_i <= devid; ++dev_i) { - if (alias) + if (alias) { amd_iommu_alias_table[dev_i] = devid_to; - set_dev_entry_from_acpi(iommu, - amd_iommu_alias_table[dev_i], - flags, ext_flags); + set_dev_entry_from_acpi(iommu, + devid_to, flags, ext_flags); + } + set_dev_entry_from_acpi(iommu, dev_i, + flags, ext_flags); } break; default: -- GitLab From 75e6bf9638992dfc0fec9c3ca10444c8e0d6a638 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Thu, 2 Jul 2009 11:21:16 +0100 Subject: [PATCH 0543/1002] intel-iommu: Introduce first_pte_in_page() to simplify PTE-setting loops On Wed, 2009-07-01 at 16:59 -0700, Linus Torvalds wrote: > I also _really_ hate how you do > > (unsigned long)pte >> VTD_PAGE_SHIFT == > (unsigned long)first_pte >> VTD_PAGE_SHIFT Kill this, in favour of just looking to see if the incremented pte pointer has 'wrapped' onto the next page. Which means we have to check it _after_ incrementing it, not before. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 2c1b2babfdc50..dcf0295a9b602 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -240,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte) return (pte->val & 3) != 0; } +static inline int first_pte_in_page(struct dma_pte *pte) +{ + return !((unsigned long)pte & ~VTD_PAGE_MASK); +} + /* * This domain is a statically identity mapping domain. * 1. This domain creats a static 1:1 mapping to all usable memory. @@ -780,13 +785,12 @@ static void dma_pte_clear_range(struct dmar_domain *domain, start_pfn = align_to_level(start_pfn + 1, 2); continue; } - while (start_pfn <= last_pfn && - (unsigned long)pte >> VTD_PAGE_SHIFT == - (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + do { dma_clear_pte(pte); start_pfn++; pte++; - } + } while (start_pfn <= last_pfn && !first_pte_in_page(pte)); + domain_flush_cache(domain, first_pte, (void *)pte - (void *)first_pte); } @@ -821,14 +825,14 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, tmp = align_to_level(tmp + 1, level + 1); continue; } - while (tmp + level_size(level) - 1 <= last_pfn && - (unsigned long)pte >> VTD_PAGE_SHIFT == - (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + do { free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); dma_clear_pte(pte); pte++; tmp += level_size(level); - } + } while (!first_pte_in_page(pte) && + tmp + level_size(level) - 1 <= last_pfn); + domain_flush_cache(domain, first_pte, (void *)pte - (void *)first_pte); @@ -1694,9 +1698,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, WARN_ON(1); } pte++; - if (!nr_pages || - (unsigned long)pte >> VTD_PAGE_SHIFT != - (unsigned long)first_pte >> VTD_PAGE_SHIFT) { + if (!nr_pages || first_pte_in_page(pte)) { domain_flush_cache(domain, first_pte, (void *)pte - (void *)first_pte); pte = NULL; -- GitLab From 6a43e574c5af7d9bd084992b1c9c3cdbc3b6c0e9 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Thu, 2 Jul 2009 12:02:34 +0100 Subject: [PATCH 0544/1002] intel-iommu: Don't keep freeing page zero in dma_pte_free_pagetable() Check dma_pte_present() and only free the page if there _is_ one. Kind of surprising that there was no warning about this. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index dcf0295a9b602..53075424a4349 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -826,8 +826,10 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, continue; } do { - free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); - dma_clear_pte(pte); + if (dma_pte_present(pte)) { + free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); + dma_clear_pte(pte); + } pte++; tmp += level_size(level); } while (!first_pte_in_page(pte) && -- GitLab From bdae997f44535ac4ebe1e055ffe59eeee946f453 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 1 Jul 2009 21:56:38 -0700 Subject: [PATCH 0545/1002] fs/notify/inotify: decrement user inotify count on close The per-user inotify_devs value is incremented each time a new file is allocated, but never decremented. This led to inotify_init failing after a limited number of calls. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eric Paris <eparis@redhat.com> --- fs/notify/inotify/inotify_user.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index ff231ad23895e..ff27a2965844c 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -296,12 +296,15 @@ static int inotify_fasync(int fd, struct file *file, int on) static int inotify_release(struct inode *ignored, struct file *file) { struct fsnotify_group *group = file->private_data; + struct user_struct *user = group->inotify_data.user; fsnotify_clear_marks_by_group(group); /* free this group, matching get was inotify_init->fsnotify_obtain_group */ fsnotify_put_group(group); + atomic_dec(&user->inotify_devs); + return 0; } -- GitLab From eab4170865cce9b8898a813b7e8024de857a01da Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:37:00 +0100 Subject: [PATCH 0546/1002] [ARM] 5567/1: at91: Support for at91sam9g10: clocks management From: Hong Xu <hong.xu@atmel.com> Add the at91sam9g10 support to the AT91 generic clock file. It takes advantage of the management by functionalities of those PLLs and clocks. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/clock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 6396680271e85..c042dcf4725fc 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -53,7 +53,7 @@ #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ || cpu_is_at91sam9g45()) -#define cpu_has_300M_plla() (0) +#define cpu_has_300M_plla() (cpu_is_at91sam9g10()) #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45())) @@ -626,7 +626,9 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock) uhpck.pmc_mask = AT91RM9200_PMC_UHP; udpck.pmc_mask = AT91RM9200_PMC_UDP; at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); - } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { + } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || + cpu_is_at91sam9263() || cpu_is_at91sam9g20() || + cpu_is_at91sam9g10()) { uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; } else if (cpu_is_at91cap9()) { -- GitLab From b784b7c03723891876c9053c589150a4062f9455 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:36:59 +0100 Subject: [PATCH 0547/1002] [ARM] 5568/1: at91: Basic support for at91sam9g10: header files From: Hong Xu <hong.xu@atmel.com> AT91sam9g10 is an ARM 926ej-s SOC. It is an evolution of the at91sam9261 with a faster clock speed: 266/133MHz. Here is the basic header file support for this product. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/include/mach/at91sam9261.h | 3 +++ arch/arm/mach-at91/include/mach/cpu.h | 7 +++++++ arch/arm/mach-at91/include/mach/hardware.h | 2 +- arch/arm/mach-at91/include/mach/timex.h | 5 +++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h index 3a348ca20773c..87de8be17484b 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9261.h +++ b/arch/arm/mach-at91/include/mach/at91sam9261.h @@ -95,6 +95,9 @@ #define AT91SAM9261_SRAM_BASE 0x00300000 /* Internal SRAM base address */ #define AT91SAM9261_SRAM_SIZE 0x00028000 /* Internal SRAM size (160Kb) */ +#define AT91SAM9G10_SRAM_BASE AT91SAM9261_SRAM_BASE /* Internal SRAM base address */ +#define AT91SAM9G10_SRAM_SIZE 0x00004000 /* Internal SRAM size (16Kb) */ + #define AT91SAM9261_ROM_BASE 0x00400000 /* Internal ROM base address */ #define AT91SAM9261_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */ diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index b73e7bf097daa..34a9502c48bce 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -21,6 +21,7 @@ #define ARCH_ID_AT91SAM9260 0x019803a0 #define ARCH_ID_AT91SAM9261 0x019703a0 #define ARCH_ID_AT91SAM9263 0x019607a0 +#define ARCH_ID_AT91SAM9G10 0x819903a0 #define ARCH_ID_AT91SAM9G20 0x019905a0 #define ARCH_ID_AT91SAM9RL64 0x019b03a0 #define ARCH_ID_AT91SAM9G45 0x819b05a0 @@ -97,6 +98,12 @@ static inline unsigned long at91cap9_rev_identify(void) #define cpu_is_at91sam9261() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9G10 +#define cpu_is_at91sam9g10() (at91_cpu_identify() == ARCH_ID_AT91SAM9G10) +#else +#define cpu_is_at91sam9g10() (0) +#endif + #ifdef CONFIG_ARCH_AT91SAM9263 #define cpu_is_at91sam9263() (at91_cpu_identify() == ARCH_ID_AT91SAM9263) #else diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index f0869170fa00e..a0df8b022df27 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h @@ -20,7 +20,7 @@ #include <mach/at91rm9200.h> #elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20) #include <mach/at91sam9260.h> -#elif defined(CONFIG_ARCH_AT91SAM9261) +#elif defined(CONFIG_ARCH_AT91SAM9261) || defined(CONFIG_ARCH_AT91SAM9G10) #include <mach/at91sam9261.h> #elif defined(CONFIG_ARCH_AT91SAM9263) #include <mach/at91sam9263.h> diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h index 38f6c4250c761..31ac2d97f14cb 100644 --- a/arch/arm/mach-at91/include/mach/timex.h +++ b/arch/arm/mach-at91/include/mach/timex.h @@ -42,6 +42,11 @@ #define AT91SAM9_MASTER_CLOCK 99300000 #define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) +#elif defined(CONFIG_ARCH_AT91SAM9G10) + +#define AT91SAM9_MASTER_CLOCK 133000000 +#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16) + #elif defined(CONFIG_ARCH_AT91SAM9263) #if defined(CONFIG_MACH_USB_A9263) -- GitLab From b319ff80852e823c3a18778c839151784990f80b Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 26 Jun 2009 15:37:01 +0100 Subject: [PATCH 0548/1002] [ARM] 5570/1: at91: Support for at91sam9g10: core chip & board support From: Hong Xu <hong.xu@atmel.com> Here are the modification to at91sam9261 files dedicated to the support of at91sam9g10. This direction has been adopted to minimize code duplication. All at91sam9261 drivers are enabled in _devices and board- files. Modificaton to peripherals that support at91sam9g10 will be added in future patches. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/Kconfig | 25 +++++++++++++++++++++++-- arch/arm/mach-at91/Makefile | 2 ++ arch/arm/mach-at91/at91sam9261.c | 22 +++++++++++++++++++++- arch/arm/mach-at91/board-sam9261ek.c | 14 ++++++++++++++ arch/arm/mach-at91/pm.c | 3 ++- 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 22309ba97fa60..8f3e15abdb62b 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -23,6 +23,12 @@ config ARCH_AT91SAM9261 select GENERIC_TIME select GENERIC_CLOCKEVENTS +config ARCH_AT91SAM9G10 + bool "AT91SAM9G10" + select CPU_ARM926T + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + config ARCH_AT91SAM9263 bool "AT91SAM9263" select CPU_ARM926T @@ -230,6 +236,21 @@ endif # ---------------------------------------------------------- +if ARCH_AT91SAM9G10 + +comment "AT91SAM9G10 Board Type" + +config MACH_AT91SAM9G10EK + bool "Atmel AT91SAM9G10-EK Evaluation Kit" + depends on ARCH_AT91SAM9G10 + help + Select this if you are using Atmel's AT91SAM9G10-EK Evaluation Kit. + <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4588> + +endif + +# ---------------------------------------------------------- + if ARCH_AT91SAM9263 comment "AT91SAM9263 Board Type" @@ -337,13 +358,13 @@ comment "AT91 Board Options" config MTD_AT91_DATAFLASH_CARD bool "Enable DataFlash Card support" - depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_ECBAT91 || MACH_SAM9_L9260 || MACH_AT91CAP9ADK || MACH_NEOCORE926) + depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_ECBAT91 || MACH_SAM9_L9260 || MACH_AT91CAP9ADK || MACH_NEOCORE926) help Enable support for the DataFlash card. config MTD_NAND_ATMEL_BUSWIDTH_16 bool "Enable 16-bit data bus interface to NAND flash" - depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_AT91SAM9G45EKES || MACH_AT91CAP9ADK) + depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK || MACH_AT91SAM9G20EK || MACH_AT91SAM9G45EKES || MACH_AT91CAP9ADK) help On AT91SAM926x boards both types of NAND flash can be present (8 and 16 bit data bus width). diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 2975f9ab861c8..4eaf80abe1009 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_AT91_PMC_UNIT) += clock.o obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o @@ -44,6 +45,7 @@ obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o # AT91SAM9261 board-specific support obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o +obj-$(CONFIG_MACH_AT91SAM9G10EK) += board-sam9261ek.o # AT91SAM9263 board-specific support obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 3acd7d7e6a423..4ecf37996c770 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -16,6 +16,7 @@ #include <asm/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <mach/cpu.h> #include <mach/at91sam9261.h> #include <mach/at91_pmc.h> #include <mach/at91_rstc.h> @@ -30,7 +31,11 @@ static struct map_desc at91sam9261_io_desc[] __initdata = { .pfn = __phys_to_pfn(AT91_BASE_SYS), .length = SZ_16K, .type = MT_DEVICE, - }, { + }, +}; + +static struct map_desc at91sam9261_sram_desc[] __initdata = { + { .virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE, .pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE), .length = AT91SAM9261_SRAM_SIZE, @@ -38,6 +43,15 @@ static struct map_desc at91sam9261_io_desc[] __initdata = { }, }; +static struct map_desc at91sam9g10_sram_desc[] __initdata = { + { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9G10_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91SAM9G10_SRAM_BASE), + .length = AT91SAM9G10_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + /* -------------------------------------------------------------------- * Clocks * -------------------------------------------------------------------- */ @@ -263,6 +277,12 @@ void __init at91sam9261_initialize(unsigned long main_clock) /* Map peripherals */ iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc)); + if (cpu_is_at91sam9g10()) + iotable_init(at91sam9g10_sram_desc, ARRAY_SIZE(at91sam9g10_sram_desc)); + else + iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc)); + + at91_arch_reset = at91sam9261_reset; pm_power_off = at91sam9261_poweroff; at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index d5266da553112..f9b19993a7a95 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -287,7 +287,11 @@ static void __init ek_add_device_ts(void) {} */ static struct at73c213_board_info at73c213_data = { .ssc_id = 1, +#if defined(CONFIG_MACH_AT91SAM9261EK) .shortname = "AT91SAM9261-EK external DAC", +#else + .shortname = "AT91SAM9G10-EK external DAC", +#endif }; #if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE) @@ -414,6 +418,9 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { .default_monspecs = &at91fb_default_stn_monspecs, .atmel_lcdfb_power_control = at91_lcdc_stn_power_control, .guard_time = 1, +#if defined(CONFIG_MACH_AT91SAM9G10EK) + .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, +#endif }; #else @@ -467,6 +474,9 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = { .default_monspecs = &at91fb_default_tft_monspecs, .atmel_lcdfb_power_control = at91_lcdc_tft_power_control, .guard_time = 1, +#if defined(CONFIG_MACH_AT91SAM9G10EK) + .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, +#endif }; #endif @@ -600,7 +610,11 @@ static void __init ek_board_init(void) at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); } +#if defined(CONFIG_MACH_AT91SAM9261EK) MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") +#else +MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK") +#endif /* Maintainer: Atmel */ .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index e26c4fe61faea..4028724d490df 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -201,7 +201,8 @@ static int at91_pm_verify_clocks(void) pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; } - } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { + } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() + || cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) { if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; -- GitLab From 9be4b17c4c900f634ab9be3d13e116aa31edb7cb Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@stericsson.com> Date: Wed, 1 Jul 2009 23:41:12 +0100 Subject: [PATCH 0549/1002] [ARM] 5579/1: Updated U300 defconfig This defconfig update selects all the new U300 drivers merged for 2.6.31-rc1 in the merge window and add defaults for the new config options. It compiles and boots nicely from initramfs on the U300. Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/configs/u300_defconfig | 92 +++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig index 2d827e1211470..4762d90012984 100644 --- a/arch/arm/configs/u300_defconfig +++ b/arch/arm/configs/u300_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.30-rc6 -# Mon Jun 1 09:18:22 2009 +# Linux kernel version: 2.6.31-rc1 +# Thu Jul 2 00:16:59 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -9,7 +9,7 @@ CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -# CONFIG_NO_IOPORT is not set +CONFIG_HAVE_TCM=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -18,13 +18,12 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y # # General setup @@ -68,7 +67,6 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_STRIP_ASM_SYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y @@ -81,8 +79,13 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set + +# +# Performance Counters +# # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y @@ -94,6 +97,10 @@ CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -106,7 +113,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y -# CONFIG_LBD is not set +CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -138,9 +145,9 @@ CONFIG_DEFAULT_IOSCHED="deadline" # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IMX is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -216,8 +223,8 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_CPU_CACHE_ROUND_ROBIN is not set -# CONFIG_OUTER_CACHE is not set CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 CONFIG_COMMON_CLKDEV=y # @@ -243,7 +250,6 @@ CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -CONFIG_ARCH_FLATMEM_HAS_HOLES=y # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_HIGHMEM is not set @@ -258,17 +264,18 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y -CONFIG_UNEVICTABLE_LRU=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set # # Boot options # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/mtdblock2 rw rootfstype=yaffs2 console=ttyAMA0,115200n8 ab3100.force=0,0x48 mtdparts=u300nand:128k@0x0(bootrecords)ro,8064k@128k(free)ro,253952k@8192k(platform) lpj=515072" +CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set @@ -359,6 +366,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -497,6 +505,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_AT24 is not set # CONFIG_EEPROM_AT25 is not set # CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -538,6 +547,7 @@ CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_GPIO is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set @@ -597,9 +607,11 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_STU300=y # # External I2C/SMBus adapter drivers @@ -620,7 +632,6 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set @@ -635,6 +646,7 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set +CONFIG_SPI_PL022=y # # SPI Protocol Masters @@ -647,6 +659,7 @@ CONFIG_POWER_SUPPLY=y # CONFIG_PDA_POWER is not set # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set # CONFIG_THERMAL_HWMON is not set @@ -657,6 +670,7 @@ CONFIG_WATCHDOG=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set +CONFIG_COH901327_WATCHDOG=y CONFIG_SSB_POSSIBLE=y # @@ -678,22 +692,9 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_PCF50633 is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# CONFIG_DAB is not set +CONFIG_AB3100_CORE=y +# CONFIG_EZX_PCAP is not set +# CONFIG_MEDIA_SUPPORT is not set # # Graphics support @@ -760,6 +761,11 @@ CONFIG_SND_JACK=y # CONFIG_SND_VERBOSE_PROCFS is not set # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set # CONFIG_SND_DRIVERS is not set # CONFIG_SND_ARM is not set # CONFIG_SND_SPI is not set @@ -770,7 +776,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_HID_SUPPORT is not set # CONFIG_USB_SUPPORT is not set CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DEBUG=y # CONFIG_MMC_UNSAFE_RESUME is not set # @@ -797,7 +803,7 @@ CONFIG_LEDS_CLASS=y # # CONFIG_LEDS_PCA9532 is not set # CONFIG_LEDS_GPIO is not set -# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_BD2802 is not set @@ -845,6 +851,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set # # SPI RTC drivers @@ -887,7 +894,10 @@ CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_LP3971 is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set @@ -900,16 +910,20 @@ CONFIG_REGULATOR=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set # # Caches @@ -1033,6 +1047,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1063,18 +1078,16 @@ CONFIG_DEBUG_INFO=y # CONFIG_PAGE_POISONING is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y - -# -# Tracers -# +CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_EVENT_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set # CONFIG_BOOT_TRACER is not set -# CONFIG_TRACE_BRANCH_PROFILING is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1109,6 +1122,7 @@ CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC32 is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_ALLOCATOR=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y -- GitLab From 4ebfc3dba59fb84b315ebb0059347dc9342a32f1 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@stericsson.com> Date: Thu, 2 Jul 2009 00:27:57 +0100 Subject: [PATCH 0550/1002] [ARM] 5581/1: U300 clock updates This adds a few default locks to the clocks (the clocks were used before the locks were initialized by code), then renames the clocks a bit to fit with the latest driver names (some changed during review). Lastly it moves the initialization of the clock debugfs entry to module_init() initcall level since the debugfs isn't up in core_initcall(). Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-u300/clock.c | 121 ++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 41 deletions(-) diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 5cd04d6751b30..111f7ea32b384 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/timer.h> #include <linux/io.h> +#include <linux/seq_file.h> #include <asm/clkdev.h> #include <mach/hardware.h> @@ -702,6 +703,7 @@ static struct clk amba_clk = { .rate = 52000000, /* this varies! */ .hw_ctrld = true, .reset = false, + .lock = __SPIN_LOCK_UNLOCKED(amba_clk.lock), }; /* @@ -720,6 +722,7 @@ static struct clk cpu_clk = { .set_rate = clk_set_rate_cpuclk, .get_rate = clk_get_rate_cpuclk, .round_rate = clk_round_rate_cpuclk, + .lock = __SPIN_LOCK_UNLOCKED(cpu_clk.lock), }; static struct clk nandif_clk = { @@ -732,6 +735,7 @@ static struct clk nandif_clk = { .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(nandif_clk.lock), }; static struct clk semi_clk = { @@ -744,6 +748,7 @@ static struct clk semi_clk = { .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(semi_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -758,6 +763,7 @@ static struct clk isp_clk = { .clk_val = U300_SYSCON_SBCER_ISP_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(isp_clk.lock), }; static struct clk cds_clk = { @@ -771,6 +777,7 @@ static struct clk cds_clk = { .clk_val = U300_SYSCON_SBCER_CDS_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(cds_clk.lock), }; #endif @@ -785,6 +792,7 @@ static struct clk dma_clk = { .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(dma_clk.lock), }; static struct clk aaif_clk = { @@ -798,6 +806,7 @@ static struct clk aaif_clk = { .clk_val = U300_SYSCON_SBCER_AAIF_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(aaif_clk.lock), }; static struct clk apex_clk = { @@ -811,6 +820,7 @@ static struct clk apex_clk = { .clk_val = U300_SYSCON_SBCER_APEX_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(apex_clk.lock), }; static struct clk video_enc_clk = { @@ -825,6 +835,7 @@ static struct clk video_enc_clk = { .clk_val = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock), }; static struct clk xgam_clk = { @@ -839,6 +850,7 @@ static struct clk xgam_clk = { .get_rate = clk_get_rate_xgamclk, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(xgam_clk.lock), }; /* This clock is used to activate the video encoder */ @@ -854,6 +866,7 @@ static struct clk ahb_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_ahb_clk, + .lock = __SPIN_LOCK_UNLOCKED(ahb_clk.lock), }; @@ -871,6 +884,7 @@ static struct clk ahb_subsys_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_ahb_clk, + .lock = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock), }; static struct clk intcon_clk = { @@ -882,6 +896,8 @@ static struct clk intcon_clk = { .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, .res_mask = U300_SYSCON_RRR_INTCON_RESET_EN, /* INTCON can be reset but not clock-gated */ + .lock = __SPIN_LOCK_UNLOCKED(intcon_clk.lock), + }; static struct clk mspro_clk = { @@ -895,6 +911,7 @@ static struct clk mspro_clk = { .clk_val = U300_SYSCON_SBCER_MSPRO_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(mspro_clk.lock), }; static struct clk emif_clk = { @@ -909,6 +926,7 @@ static struct clk emif_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_emif_clk, + .lock = __SPIN_LOCK_UNLOCKED(emif_clk.lock), }; @@ -926,6 +944,7 @@ static struct clk fast_clk = { .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(fast_clk.lock), }; static struct clk mmcsd_clk = { @@ -942,6 +961,7 @@ static struct clk mmcsd_clk = { .round_rate = clk_round_rate_mclk, .disable = syscon_clk_disable, .enable = syscon_clk_enable, + .lock = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock), }; static struct clk i2s0_clk = { @@ -956,6 +976,7 @@ static struct clk i2s0_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock), }; static struct clk i2s1_clk = { @@ -970,6 +991,7 @@ static struct clk i2s1_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock), }; static struct clk i2c0_clk = { @@ -984,6 +1006,7 @@ static struct clk i2c0_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock), }; static struct clk i2c1_clk = { @@ -998,6 +1021,7 @@ static struct clk i2c1_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock), }; static struct clk spi_clk = { @@ -1012,6 +1036,7 @@ static struct clk spi_clk = { .enable = syscon_clk_enable, .disable = syscon_clk_disable, .get_rate = clk_get_rate_i2s_i2c_spi, + .lock = __SPIN_LOCK_UNLOCKED(spi_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -1026,6 +1051,7 @@ static struct clk uart1_clk = { .clk_val = U300_SYSCON_SBCER_UART1_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(uart1_clk.lock), }; #endif @@ -1044,6 +1070,7 @@ static struct clk slow_clk = { .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(slow_clk.lock), }; /* TODO: implement SYSCON clock? */ @@ -1055,6 +1082,7 @@ static struct clk wdog_clk = { .rate = 32768, .reset = false, /* This is always on, cannot be enabled/disabled or reset */ + .lock = __SPIN_LOCK_UNLOCKED(wdog_clk.lock), }; /* This one is hardwired to PLL13 */ @@ -1069,6 +1097,7 @@ static struct clk uart_clk = { .clk_val = U300_SYSCON_SBCER_UART_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(uart_clk.lock), }; static struct clk keypad_clk = { @@ -1082,6 +1111,7 @@ static struct clk keypad_clk = { .clk_val = U300_SYSCON_SBCER_KEYPAD_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(keypad_clk.lock), }; static struct clk gpio_clk = { @@ -1095,6 +1125,7 @@ static struct clk gpio_clk = { .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(gpio_clk.lock), }; static struct clk rtc_clk = { @@ -1106,6 +1137,7 @@ static struct clk rtc_clk = { .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, .res_mask = U300_SYSCON_RSR_RTC_RESET_EN, /* This clock is always on, cannot be enabled/disabled */ + .lock = __SPIN_LOCK_UNLOCKED(rtc_clk.lock), }; static struct clk bustr_clk = { @@ -1119,6 +1151,7 @@ static struct clk bustr_clk = { .clk_val = U300_SYSCON_SBCER_BTR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(bustr_clk.lock), }; static struct clk evhist_clk = { @@ -1132,6 +1165,7 @@ static struct clk evhist_clk = { .clk_val = U300_SYSCON_SBCER_EH_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(evhist_clk.lock), }; static struct clk timer_clk = { @@ -1145,6 +1179,7 @@ static struct clk timer_clk = { .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(timer_clk.lock), }; static struct clk app_timer_clk = { @@ -1158,6 +1193,7 @@ static struct clk app_timer_clk = { .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock), }; #ifdef CONFIG_MACH_U300_BS335 @@ -1172,6 +1208,7 @@ static struct clk ppm_clk = { .clk_val = U300_SYSCON_SBCER_PPM_CLK_EN, .enable = syscon_clk_enable, .disable = syscon_clk_disable, + .lock = __SPIN_LOCK_UNLOCKED(ppm_clk.lock), }; #endif @@ -1187,53 +1224,53 @@ static struct clk ppm_clk = { */ static struct clk_lookup lookups[] = { /* Connected directly to the AMBA bus */ - DEF_LOOKUP("amba", &amba_clk), - DEF_LOOKUP("cpu", &cpu_clk), - DEF_LOOKUP("nandif", &nandif_clk), - DEF_LOOKUP("semi", &semi_clk), + DEF_LOOKUP("amba", &amba_clk), + DEF_LOOKUP("cpu", &cpu_clk), + DEF_LOOKUP("fsmc", &nandif_clk), + DEF_LOOKUP("semi", &semi_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("isp", &isp_clk), - DEF_LOOKUP("cds", &cds_clk), + DEF_LOOKUP("isp", &isp_clk), + DEF_LOOKUP("cds", &cds_clk), #endif - DEF_LOOKUP("dma", &dma_clk), - DEF_LOOKUP("aaif", &aaif_clk), - DEF_LOOKUP("apex", &apex_clk), + DEF_LOOKUP("dma", &dma_clk), + DEF_LOOKUP("msl", &aaif_clk), + DEF_LOOKUP("apex", &apex_clk), DEF_LOOKUP("video_enc", &video_enc_clk), - DEF_LOOKUP("xgam", &xgam_clk), - DEF_LOOKUP("ahb", &ahb_clk), + DEF_LOOKUP("xgam", &xgam_clk), + DEF_LOOKUP("ahb", &ahb_clk), /* AHB bridge clocks */ - DEF_LOOKUP("ahb", &ahb_subsys_clk), - DEF_LOOKUP("intcon", &intcon_clk), - DEF_LOOKUP("mspro", &mspro_clk), - DEF_LOOKUP("pl172", &emif_clk), + DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk), + DEF_LOOKUP("intcon", &intcon_clk), + DEF_LOOKUP("mspro", &mspro_clk), + DEF_LOOKUP("pl172", &emif_clk), /* FAST bridge clocks */ - DEF_LOOKUP("fast", &fast_clk), - DEF_LOOKUP("mmci", &mmcsd_clk), + DEF_LOOKUP("fast", &fast_clk), + DEF_LOOKUP("mmci", &mmcsd_clk), /* * The .0 and .1 identifiers on these comes from the platform device * .id field and are assigned when the platform devices are registered. */ - DEF_LOOKUP("i2s.0", &i2s0_clk), - DEF_LOOKUP("i2s.1", &i2s1_clk), - DEF_LOOKUP("stddci2c.0", &i2c0_clk), - DEF_LOOKUP("stddci2c.1", &i2c1_clk), - DEF_LOOKUP("pl022", &spi_clk), + DEF_LOOKUP("i2s.0", &i2s0_clk), + DEF_LOOKUP("i2s.1", &i2s1_clk), + DEF_LOOKUP("stu300.0", &i2c0_clk), + DEF_LOOKUP("stu300.1", &i2c1_clk), + DEF_LOOKUP("pl022", &spi_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("uart1", &uart1_clk), + DEF_LOOKUP("uart1", &uart1_clk), #endif /* SLOW bridge clocks */ - DEF_LOOKUP("slow", &slow_clk), - DEF_LOOKUP("wdog", &wdog_clk), - DEF_LOOKUP("uart0", &uart_clk), - DEF_LOOKUP("apptimer", &app_timer_clk), - DEF_LOOKUP("keypad", &keypad_clk), + DEF_LOOKUP("slow", &slow_clk), + DEF_LOOKUP("coh901327_wdog", &wdog_clk), + DEF_LOOKUP("uart0", &uart_clk), + DEF_LOOKUP("apptimer", &app_timer_clk), + DEF_LOOKUP("coh901461-keypad", &keypad_clk), DEF_LOOKUP("u300-gpio", &gpio_clk), - DEF_LOOKUP("rtc0", &rtc_clk), - DEF_LOOKUP("bustr", &bustr_clk), - DEF_LOOKUP("evhist", &evhist_clk), - DEF_LOOKUP("timer", &timer_clk), + DEF_LOOKUP("rtc-coh901331", &rtc_clk), + DEF_LOOKUP("bustr", &bustr_clk), + DEF_LOOKUP("evhist", &evhist_clk), + DEF_LOOKUP("timer", &timer_clk), #ifdef CONFIG_MACH_U300_BS335 - DEF_LOOKUP("ppm", &ppm_clk), + DEF_LOOKUP("ppm", &ppm_clk), #endif }; @@ -1427,16 +1464,20 @@ static const struct file_operations u300_clocks_operations = { .release = single_release, }; -static void init_clk_read_procfs(void) +static int __init init_clk_read_debugfs(void) { /* Expose a simple debugfs interface to view all clocks */ (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO, - NULL, NULL, &u300_clocks_operations); -} -#else -static inline void init_clk_read_procfs(void) -{ + NULL, NULL, + &u300_clocks_operations); + return 0; } +/* + * This needs to come in after the core_initcall() for the + * overall clocks, because debugfs is not available until + * the subsystems come up. + */ +module_init(init_clk_read_debugfs); #endif static int __init u300_clock_init(void) @@ -1462,8 +1503,6 @@ static int __init u300_clock_init(void) clk_register(); - init_clk_read_procfs(); - /* * Some of these may be on when we boot the system so make sure they * are turned OFF. -- GitLab From 1bc6f83813441d15a74dfa97966fb68fa1bdec76 Mon Sep 17 00:00:00 2001 From: Joerg Roedel <joerg.roedel@amd.com> Date: Thu, 2 Jul 2009 18:32:05 +0200 Subject: [PATCH 0551/1002] amd-iommu: set evt_buf_size correctly The setting of this variable got lost during the suspend/resume implementation. But keeping this variable zero causes a divide-by-zero error in the interrupt handler. This patch fixes this. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> --- arch/x86/kernel/amd_iommu_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index ec72c7779d6b3..c1b17e97252e0 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -472,6 +472,8 @@ static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) if (iommu->evt_buf == NULL) return NULL; + iommu->evt_buf_size = EVT_BUFFER_SIZE; + return iommu->evt_buf; } -- GitLab From f597bb19ccd034cbcf05e1194238e2c8d9505a8a Mon Sep 17 00:00:00 2001 From: Chris Mason <chris.mason@oracle.com> Date: Sat, 27 Jun 2009 21:06:22 -0400 Subject: [PATCH 0552/1002] Btrfs: don't log the inode in file_write while growing the file --- fs/btrfs/file.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 126477eaecf56..7c3cd248d8d61 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -151,7 +151,10 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, } if (end_pos > isize) { i_size_write(inode, end_pos); - btrfs_update_inode(trans, root, inode); + /* we've only changed i_size in ram, and we haven't updated + * the disk i_size. There is no need to log the inode + * at this time. + */ } err = btrfs_end_transaction(trans, root); out_unlock: -- GitLab From c8a894d77de4a1e0a544577fd4eabc9aacd453a8 Mon Sep 17 00:00:00 2001 From: Chris Mason <chris.mason@oracle.com> Date: Sat, 27 Jun 2009 21:07:03 -0400 Subject: [PATCH 0553/1002] Btrfs: fix the file clone ioctl for preallocated extents --- fs/btrfs/ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index eff18f5b53620..9f4db848db10d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1028,7 +1028,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, struct btrfs_file_extent_item); comp = btrfs_file_extent_compression(leaf, extent); type = btrfs_file_extent_type(leaf, extent); - if (type == BTRFS_FILE_EXTENT_REG) { + if (type == BTRFS_FILE_EXTENT_REG || + type == BTRFS_FILE_EXTENT_PREALLOC) { disko = btrfs_file_extent_disk_bytenr(leaf, extent); diskl = btrfs_file_extent_disk_num_bytes(leaf, @@ -1051,7 +1052,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, new_key.objectid = inode->i_ino; new_key.offset = key.offset + destoff - off; - if (type == BTRFS_FILE_EXTENT_REG) { + if (type == BTRFS_FILE_EXTENT_REG || + type == BTRFS_FILE_EXTENT_PREALLOC) { ret = btrfs_insert_empty_item(trans, root, path, &new_key, size); if (ret) -- GitLab From a970b0a16cc416a509d5ae8b1d70978664e6f4fe Mon Sep 17 00:00:00 2001 From: Josef Bacik <jbacik@redhat.com> Date: Sat, 27 Jun 2009 21:07:34 -0400 Subject: [PATCH 0554/1002] Btrfs: account for space we may use in fallocate Using Eric Sandeen's xfstest for fallocate, you can easily trigger a ENOSPC panic on btrfs. This is because we do not account for data we may use when doing the fallocate. This patch fixes the problem by properly reserving space, and then just freeing it when we are done. The reservation stuff was made with delalloc in mind, so its a little crude for this case, but it keeps the box from panicing. Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com> --- fs/btrfs/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5b68330f85852..1eacc78f66142 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5103,6 +5103,7 @@ static long btrfs_fallocate(struct inode *inode, int mode, u64 mask = BTRFS_I(inode)->root->sectorsize - 1; struct extent_map *em; struct btrfs_trans_handle *trans; + struct btrfs_root *root; int ret; alloc_start = offset & ~mask; @@ -5121,6 +5122,13 @@ static long btrfs_fallocate(struct inode *inode, int mode, goto out; } + root = BTRFS_I(inode)->root; + + ret = btrfs_check_data_free_space(root, inode, + alloc_end - alloc_start); + if (ret) + goto out; + locked_end = alloc_end - 1; while (1) { struct btrfs_ordered_extent *ordered; @@ -5128,7 +5136,7 @@ static long btrfs_fallocate(struct inode *inode, int mode, trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1); if (!trans) { ret = -EIO; - goto out; + goto out_free; } /* the extent lock is ordered inside the running @@ -5189,6 +5197,8 @@ static long btrfs_fallocate(struct inode *inode, int mode, GFP_NOFS); btrfs_end_transaction(trans, BTRFS_I(inode)->root); +out_free: + btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start); out: mutex_unlock(&inode->i_mutex); return ret; -- GitLab From 2c47e605a91dde6b0514f689645e7ab336c8592a Mon Sep 17 00:00:00 2001 From: Yan Zheng <zheng.yan@oracle.com> Date: Sat, 27 Jun 2009 21:07:35 -0400 Subject: [PATCH 0555/1002] Btrfs: update backrefs while dropping snapshot The new backref format has restriction on type of backref item. If a tree block isn't referenced by its owner tree, full backrefs must be used for the pointers in it. When a tree block loses its owner tree's reference, backrefs for the pointers in it should be updated to full backrefs. Current btrfs_drop_snapshot misses the code that updates backrefs, so it's unsafe for general use. This patch adds backrefs update code to btrfs_drop_snapshot. It isn't a problem in the restricted form btrfs_drop_snapshot is used today, but for general snapshot deletion this update is required. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com> --- fs/btrfs/ctree.h | 3 +- fs/btrfs/extent-tree.c | 564 ++++++++++++++++++++++++++++------------- fs/btrfs/relocation.c | 5 +- fs/btrfs/transaction.c | 4 +- 4 files changed, 395 insertions(+), 181 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 03441a99ea38a..a404ecc53eb1e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2076,8 +2076,7 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); -int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root - *root); +int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref); int btrfs_drop_subtree(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *node, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index edc7d208c5ce6..cd64cfc14f7f0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -990,15 +990,13 @@ static inline int extent_ref_type(u64 parent, u64 owner) return type; } -static int find_next_key(struct btrfs_path *path, struct btrfs_key *key) +static int find_next_key(struct btrfs_path *path, int level, + struct btrfs_key *key) { - int level; - BUG_ON(!path->keep_locks); - for (level = 0; level < BTRFS_MAX_LEVEL; level++) { + for (; level < BTRFS_MAX_LEVEL; level++) { if (!path->nodes[level]) break; - btrfs_assert_tree_locked(path->nodes[level]); if (path->slots[level] + 1 >= btrfs_header_nritems(path->nodes[level])) continue; @@ -1158,7 +1156,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, * For simplicity, we just do not add new inline back * ref if there is any kind of item for this block */ - if (find_next_key(path, &key) == 0 && key.objectid == bytenr && + if (find_next_key(path, 0, &key) == 0 && + key.objectid == bytenr && key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) { err = -EAGAIN; goto out; @@ -4128,6 +4127,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, return buf; } +#if 0 int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *leaf) { @@ -4171,8 +4171,6 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, return 0; } -#if 0 - static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_leaf_ref *ref) @@ -4553,262 +4551,471 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, } #endif +struct walk_control { + u64 refs[BTRFS_MAX_LEVEL]; + u64 flags[BTRFS_MAX_LEVEL]; + struct btrfs_key update_progress; + int stage; + int level; + int shared_level; + int update_ref; + int keep_locks; +}; + +#define DROP_REFERENCE 1 +#define UPDATE_BACKREF 2 + /* - * helper function for drop_subtree, this function is similar to - * walk_down_tree. The main difference is that it checks reference - * counts while tree blocks are locked. + * hepler to process tree block while walking down the tree. + * + * when wc->stage == DROP_REFERENCE, this function checks + * reference count of the block. if the block is shared and + * we need update back refs for the subtree rooted at the + * block, this function changes wc->stage to UPDATE_BACKREF + * + * when wc->stage == UPDATE_BACKREF, this function updates + * back refs for pointers in the block. + * + * NOTE: return value 1 means we should stop walking down. */ -static noinline int walk_down_tree(struct btrfs_trans_handle *trans, +static noinline int walk_down_proc(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct btrfs_path *path, int *level) + struct btrfs_path *path, + struct walk_control *wc) { - struct extent_buffer *next; - struct extent_buffer *cur; - struct extent_buffer *parent; - u64 bytenr; - u64 ptr_gen; - u64 refs; - u64 flags; - u32 blocksize; + int level = wc->level; + struct extent_buffer *eb = path->nodes[level]; + struct btrfs_key key; + u64 flag = BTRFS_BLOCK_FLAG_FULL_BACKREF; int ret; - cur = path->nodes[*level]; - ret = btrfs_lookup_extent_info(trans, root, cur->start, cur->len, - &refs, &flags); - BUG_ON(ret); - if (refs > 1) - goto out; + if (wc->stage == UPDATE_BACKREF && + btrfs_header_owner(eb) != root->root_key.objectid) + return 1; - BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)); + /* + * when reference count of tree block is 1, it won't increase + * again. once full backref flag is set, we never clear it. + */ + if ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) || + (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag))) { + BUG_ON(!path->locks[level]); + ret = btrfs_lookup_extent_info(trans, root, + eb->start, eb->len, + &wc->refs[level], + &wc->flags[level]); + BUG_ON(ret); + BUG_ON(wc->refs[level] == 0); + } - while (*level >= 0) { - cur = path->nodes[*level]; - if (*level == 0) { - ret = btrfs_drop_leaf_ref(trans, root, cur); - BUG_ON(ret); - clean_tree_block(trans, root, cur); - break; - } - if (path->slots[*level] >= btrfs_header_nritems(cur)) { - clean_tree_block(trans, root, cur); - break; + if (wc->stage == DROP_REFERENCE && + wc->update_ref && wc->refs[level] > 1) { + BUG_ON(eb == root->node); + BUG_ON(path->slots[level] > 0); + if (level == 0) + btrfs_item_key_to_cpu(eb, &key, path->slots[level]); + else + btrfs_node_key_to_cpu(eb, &key, path->slots[level]); + if (btrfs_header_owner(eb) == root->root_key.objectid && + btrfs_comp_cpu_keys(&key, &wc->update_progress) >= 0) { + wc->stage = UPDATE_BACKREF; + wc->shared_level = level; } + } - bytenr = btrfs_node_blockptr(cur, path->slots[*level]); - blocksize = btrfs_level_size(root, *level - 1); - ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); + if (wc->stage == DROP_REFERENCE) { + if (wc->refs[level] > 1) + return 1; - next = read_tree_block(root, bytenr, blocksize, ptr_gen); - btrfs_tree_lock(next); - btrfs_set_lock_blocking(next); + if (path->locks[level] && !wc->keep_locks) { + btrfs_tree_unlock(eb); + path->locks[level] = 0; + } + return 0; + } - ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize, - &refs, &flags); + /* wc->stage == UPDATE_BACKREF */ + if (!(wc->flags[level] & flag)) { + BUG_ON(!path->locks[level]); + ret = btrfs_inc_ref(trans, root, eb, 1); BUG_ON(ret); - if (refs > 1) { - parent = path->nodes[*level]; - ret = btrfs_free_extent(trans, root, bytenr, - blocksize, parent->start, - btrfs_header_owner(parent), - *level - 1, 0); + ret = btrfs_dec_ref(trans, root, eb, 0); + BUG_ON(ret); + ret = btrfs_set_disk_extent_flags(trans, root, eb->start, + eb->len, flag, 0); + BUG_ON(ret); + wc->flags[level] |= flag; + } + + /* + * the block is shared by multiple trees, so it's not good to + * keep the tree lock + */ + if (path->locks[level] && level > 0) { + btrfs_tree_unlock(eb); + path->locks[level] = 0; + } + return 0; +} + +/* + * hepler to process tree block while walking up the tree. + * + * when wc->stage == DROP_REFERENCE, this function drops + * reference count on the block. + * + * when wc->stage == UPDATE_BACKREF, this function changes + * wc->stage back to DROP_REFERENCE if we changed wc->stage + * to UPDATE_BACKREF previously while processing the block. + * + * NOTE: return value 1 means we should stop walking up. + */ +static noinline int walk_up_proc(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + struct walk_control *wc) +{ + int ret = 0; + int level = wc->level; + struct extent_buffer *eb = path->nodes[level]; + u64 parent = 0; + + if (wc->stage == UPDATE_BACKREF) { + BUG_ON(wc->shared_level < level); + if (level < wc->shared_level) + goto out; + + BUG_ON(wc->refs[level] <= 1); + ret = find_next_key(path, level + 1, &wc->update_progress); + if (ret > 0) + wc->update_ref = 0; + + wc->stage = DROP_REFERENCE; + wc->shared_level = -1; + path->slots[level] = 0; + + /* + * check reference count again if the block isn't locked. + * we should start walking down the tree again if reference + * count is one. + */ + if (!path->locks[level]) { + BUG_ON(level == 0); + btrfs_tree_lock(eb); + btrfs_set_lock_blocking(eb); + path->locks[level] = 1; + + ret = btrfs_lookup_extent_info(trans, root, + eb->start, eb->len, + &wc->refs[level], + &wc->flags[level]); BUG_ON(ret); - path->slots[*level]++; - btrfs_tree_unlock(next); - free_extent_buffer(next); - continue; + BUG_ON(wc->refs[level] == 0); + if (wc->refs[level] == 1) { + btrfs_tree_unlock(eb); + path->locks[level] = 0; + return 1; + } + } else { + BUG_ON(level != 0); } + } - BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)); + /* wc->stage == DROP_REFERENCE */ + BUG_ON(wc->refs[level] > 1 && !path->locks[level]); - *level = btrfs_header_level(next); - path->nodes[*level] = next; - path->slots[*level] = 0; - path->locks[*level] = 1; - cond_resched(); + if (wc->refs[level] == 1) { + if (level == 0) { + if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) + ret = btrfs_dec_ref(trans, root, eb, 1); + else + ret = btrfs_dec_ref(trans, root, eb, 0); + BUG_ON(ret); + } + /* make block locked assertion in clean_tree_block happy */ + if (!path->locks[level] && + btrfs_header_generation(eb) == trans->transid) { + btrfs_tree_lock(eb); + btrfs_set_lock_blocking(eb); + path->locks[level] = 1; + } + clean_tree_block(trans, root, eb); + } + + if (eb == root->node) { + if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) + parent = eb->start; + else + BUG_ON(root->root_key.objectid != + btrfs_header_owner(eb)); + } else { + if (wc->flags[level + 1] & BTRFS_BLOCK_FLAG_FULL_BACKREF) + parent = path->nodes[level + 1]->start; + else + BUG_ON(root->root_key.objectid != + btrfs_header_owner(path->nodes[level + 1])); } -out: - if (path->nodes[*level] == root->node) - parent = path->nodes[*level]; - else - parent = path->nodes[*level + 1]; - bytenr = path->nodes[*level]->start; - blocksize = path->nodes[*level]->len; - ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent->start, - btrfs_header_owner(parent), *level, 0); + ret = btrfs_free_extent(trans, root, eb->start, eb->len, parent, + root->root_key.objectid, level, 0); BUG_ON(ret); +out: + wc->refs[level] = 0; + wc->flags[level] = 0; + return ret; +} + +static noinline int walk_down_tree(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + struct walk_control *wc) +{ + struct extent_buffer *next; + struct extent_buffer *cur; + u64 bytenr; + u64 ptr_gen; + u32 blocksize; + int level = wc->level; + int ret; + + while (level >= 0) { + cur = path->nodes[level]; + BUG_ON(path->slots[level] >= btrfs_header_nritems(cur)); - if (path->locks[*level]) { - btrfs_tree_unlock(path->nodes[*level]); - path->locks[*level] = 0; + ret = walk_down_proc(trans, root, path, wc); + if (ret > 0) + break; + + if (level == 0) + break; + + bytenr = btrfs_node_blockptr(cur, path->slots[level]); + blocksize = btrfs_level_size(root, level - 1); + ptr_gen = btrfs_node_ptr_generation(cur, path->slots[level]); + + next = read_tree_block(root, bytenr, blocksize, ptr_gen); + btrfs_tree_lock(next); + btrfs_set_lock_blocking(next); + + level--; + BUG_ON(level != btrfs_header_level(next)); + path->nodes[level] = next; + path->slots[level] = 0; + path->locks[level] = 1; + wc->level = level; } - free_extent_buffer(path->nodes[*level]); - path->nodes[*level] = NULL; - *level += 1; - cond_resched(); return 0; } -/* - * helper for dropping snapshots. This walks back up the tree in the path - * to find the first node higher up where we haven't yet gone through - * all the slots - */ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - int *level, int max_level) + struct walk_control *wc, int max_level) { - struct btrfs_root_item *root_item = &root->root_item; - int i; - int slot; + int level = wc->level; int ret; - for (i = *level; i < max_level && path->nodes[i]; i++) { - slot = path->slots[i]; - if (slot + 1 < btrfs_header_nritems(path->nodes[i])) { - /* - * there is more work to do in this level. - * Update the drop_progress marker to reflect - * the work we've done so far, and then bump - * the slot number - */ - path->slots[i]++; - WARN_ON(*level == 0); - if (max_level == BTRFS_MAX_LEVEL) { - btrfs_node_key(path->nodes[i], - &root_item->drop_progress, - path->slots[i]); - root_item->drop_level = i; - } - *level = i; + path->slots[level] = btrfs_header_nritems(path->nodes[level]); + while (level < max_level && path->nodes[level]) { + wc->level = level; + if (path->slots[level] + 1 < + btrfs_header_nritems(path->nodes[level])) { + path->slots[level]++; return 0; } else { - struct extent_buffer *parent; - - /* - * this whole node is done, free our reference - * on it and go up one level - */ - if (path->nodes[*level] == root->node) - parent = path->nodes[*level]; - else - parent = path->nodes[*level + 1]; + ret = walk_up_proc(trans, root, path, wc); + if (ret > 0) + return 0; - clean_tree_block(trans, root, path->nodes[i]); - ret = btrfs_free_extent(trans, root, - path->nodes[i]->start, - path->nodes[i]->len, - parent->start, - btrfs_header_owner(parent), - *level, 0); - BUG_ON(ret); - if (path->locks[*level]) { - btrfs_tree_unlock(path->nodes[i]); - path->locks[i] = 0; + if (path->locks[level]) { + btrfs_tree_unlock(path->nodes[level]); + path->locks[level] = 0; } - free_extent_buffer(path->nodes[i]); - path->nodes[i] = NULL; - *level = i + 1; + free_extent_buffer(path->nodes[level]); + path->nodes[level] = NULL; + level++; } } return 1; } /* - * drop the reference count on the tree rooted at 'snap'. This traverses - * the tree freeing any blocks that have a ref count of zero after being - * decremented. + * drop a subvolume tree. + * + * this function traverses the tree freeing any blocks that only + * referenced by the tree. + * + * when a shared tree block is found. this function decreases its + * reference count by one. if update_ref is true, this function + * also make sure backrefs for the shared block and all lower level + * blocks are properly updated. */ -int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root - *root) +int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref) { - int ret = 0; - int wret; - int level; struct btrfs_path *path; - int update_count; + struct btrfs_trans_handle *trans; + struct btrfs_root *tree_root = root->fs_info->tree_root; struct btrfs_root_item *root_item = &root->root_item; + struct walk_control *wc; + struct btrfs_key key; + int err = 0; + int ret; + int level; path = btrfs_alloc_path(); BUG_ON(!path); - level = btrfs_header_level(root->node); + wc = kzalloc(sizeof(*wc), GFP_NOFS); + BUG_ON(!wc); + + trans = btrfs_start_transaction(tree_root, 1); + if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { + level = btrfs_header_level(root->node); path->nodes[level] = btrfs_lock_root_node(root); btrfs_set_lock_blocking(path->nodes[level]); path->slots[level] = 0; path->locks[level] = 1; + memset(&wc->update_progress, 0, + sizeof(wc->update_progress)); } else { - struct btrfs_key key; - struct btrfs_disk_key found_key; - struct extent_buffer *node; - btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); + memcpy(&wc->update_progress, &key, + sizeof(wc->update_progress)); + level = root_item->drop_level; + BUG_ON(level == 0); path->lowest_level = level; - wret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (wret < 0) { - ret = wret; + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + path->lowest_level = 0; + if (ret < 0) { + err = ret; goto out; } - node = path->nodes[level]; - btrfs_node_key(node, &found_key, path->slots[level]); - WARN_ON(memcmp(&found_key, &root_item->drop_progress, - sizeof(found_key))); + btrfs_node_key_to_cpu(path->nodes[level], &key, + path->slots[level]); + WARN_ON(memcmp(&key, &wc->update_progress, sizeof(key))); + /* * unlock our path, this is safe because only this * function is allowed to delete this snapshot */ btrfs_unlock_up_safe(path, 0); + + level = btrfs_header_level(root->node); + while (1) { + btrfs_tree_lock(path->nodes[level]); + btrfs_set_lock_blocking(path->nodes[level]); + + ret = btrfs_lookup_extent_info(trans, root, + path->nodes[level]->start, + path->nodes[level]->len, + &wc->refs[level], + &wc->flags[level]); + BUG_ON(ret); + BUG_ON(wc->refs[level] == 0); + + if (level == root_item->drop_level) + break; + + btrfs_tree_unlock(path->nodes[level]); + WARN_ON(wc->refs[level] != 1); + level--; + } } + + wc->level = level; + wc->shared_level = -1; + wc->stage = DROP_REFERENCE; + wc->update_ref = update_ref; + wc->keep_locks = 0; + while (1) { - unsigned long update; - wret = walk_down_tree(trans, root, path, &level); - if (wret > 0) + ret = walk_down_tree(trans, root, path, wc); + if (ret < 0) { + err = ret; break; - if (wret < 0) - ret = wret; + } - wret = walk_up_tree(trans, root, path, &level, - BTRFS_MAX_LEVEL); - if (wret > 0) + ret = walk_up_tree(trans, root, path, wc, BTRFS_MAX_LEVEL); + if (ret < 0) { + err = ret; break; - if (wret < 0) - ret = wret; - if (trans->transaction->in_commit || - trans->transaction->delayed_refs.flushing) { - ret = -EAGAIN; + } + + if (ret > 0) { + BUG_ON(wc->stage != DROP_REFERENCE); break; } - for (update_count = 0; update_count < 16; update_count++) { + + if (wc->stage == DROP_REFERENCE) { + level = wc->level; + btrfs_node_key(path->nodes[level], + &root_item->drop_progress, + path->slots[level]); + root_item->drop_level = level; + } + + BUG_ON(wc->level == 0); + if (trans->transaction->in_commit || + trans->transaction->delayed_refs.flushing) { + ret = btrfs_update_root(trans, tree_root, + &root->root_key, + root_item); + BUG_ON(ret); + + btrfs_end_transaction(trans, tree_root); + trans = btrfs_start_transaction(tree_root, 1); + } else { + unsigned long update; update = trans->delayed_ref_updates; trans->delayed_ref_updates = 0; if (update) - btrfs_run_delayed_refs(trans, root, update); - else - break; + btrfs_run_delayed_refs(trans, tree_root, + update); } } + btrfs_release_path(root, path); + BUG_ON(err); + + ret = btrfs_del_root(trans, tree_root, &root->root_key); + BUG_ON(ret); + + free_extent_buffer(root->node); + free_extent_buffer(root->commit_root); + kfree(root); out: + btrfs_end_transaction(trans, tree_root); + kfree(wc); btrfs_free_path(path); - return ret; + return err; } +/* + * drop subtree rooted at tree block 'node'. + * + * NOTE: this function will unlock and release tree block 'node' + */ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *node, struct extent_buffer *parent) { struct btrfs_path *path; + struct walk_control *wc; int level; int parent_level; int ret = 0; int wret; + BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); + path = btrfs_alloc_path(); BUG_ON(!path); + wc = kzalloc(sizeof(*wc), GFP_NOFS); + BUG_ON(!wc); + btrfs_assert_tree_locked(parent); parent_level = btrfs_header_level(parent); extent_buffer_get(parent); @@ -4817,24 +5024,33 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, btrfs_assert_tree_locked(node); level = btrfs_header_level(node); - extent_buffer_get(node); path->nodes[level] = node; path->slots[level] = 0; + path->locks[level] = 1; + + wc->refs[parent_level] = 1; + wc->flags[parent_level] = BTRFS_BLOCK_FLAG_FULL_BACKREF; + wc->level = level; + wc->shared_level = -1; + wc->stage = DROP_REFERENCE; + wc->update_ref = 0; + wc->keep_locks = 1; while (1) { - wret = walk_down_tree(trans, root, path, &level); - if (wret < 0) + wret = walk_down_tree(trans, root, path, wc); + if (wret < 0) { ret = wret; - if (wret != 0) break; + } - wret = walk_up_tree(trans, root, path, &level, parent_level); + wret = walk_up_tree(trans, root, path, wc, parent_level); if (wret < 0) ret = wret; if (wret != 0) break; } + kfree(wc); btrfs_free_path(path); return ret; } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b23dc209ae103..008397934778d 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1788,7 +1788,7 @@ static void merge_func(struct btrfs_work *work) btrfs_end_transaction(trans, root); } - btrfs_drop_dead_root(reloc_root); + btrfs_drop_snapshot(reloc_root, 0); if (atomic_dec_and_test(async->num_pending)) complete(async->done); @@ -2075,9 +2075,6 @@ static int do_relocation(struct btrfs_trans_handle *trans, ret = btrfs_drop_subtree(trans, root, eb, upper->eb); BUG_ON(ret); - - btrfs_tree_unlock(eb); - free_extent_buffer(eb); } if (!lowest) { btrfs_tree_unlock(upper->eb); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 4e83457ea253e..2dbf1c1f56ee4 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -593,6 +593,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) return 0; } +#if 0 /* * when dropping snapshots, we generate a ton of delayed refs, and it makes * sense not to join the transaction while it is trying to flush the current @@ -681,6 +682,7 @@ int btrfs_drop_dead_root(struct btrfs_root *root) btrfs_btree_balance_dirty(tree_root, nr); return ret; } +#endif /* * new snapshots need to be created at a very specific time in the @@ -1081,7 +1083,7 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) while (!list_empty(&list)) { root = list_entry(list.next, struct btrfs_root, root_list); list_del_init(&root->root_list); - btrfs_drop_dead_root(root); + btrfs_drop_snapshot(root, 0); } return 0; } -- GitLab From 9427216476d4fa75103f39d4b228c47d56ba20da Mon Sep 17 00:00:00 2001 From: Chris Mason <chris.mason@oracle.com> Date: Thu, 2 Jul 2009 12:26:06 -0400 Subject: [PATCH 0556/1002] Btrfs: honor nodatacow/sum mount options for new files The btrfs attr patches unconditionally inherited the inode flags field without honoring nodatacow and nodatasum. This fix makes sure we properly record the nodatacow/sum mount options in new inodes. Signed-off-by: Chris Mason <chris.mason@oracle.com> --- fs/btrfs/inode.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1eacc78f66142..a48c084f6d3a7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3587,12 +3587,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, owner = 1; BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, alloc_hint, owner); - if ((mode & S_IFREG)) { - if (btrfs_test_opt(root, NODATASUM)) - BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; - if (btrfs_test_opt(root, NODATACOW)) - BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; - } key[0].objectid = objectid; btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); @@ -3647,6 +3641,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, btrfs_inherit_iflags(inode, dir); + if ((mode & S_IFREG)) { + if (btrfs_test_opt(root, NODATASUM)) + BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; + if (btrfs_test_opt(root, NODATACOW)) + BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; + } + insert_inode_hash(inode); inode_tree_add(inode); return inode; -- GitLab From 9b627e9bf49ebfeb060dfae0435bdba06cf27cb8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Thu, 2 Jul 2009 13:50:58 -0400 Subject: [PATCH 0557/1002] Btrfs: fix use after free in btrfs_start_workers fail path worker memory is already freed on one fail path in btrfs_start_workers, but is still dereferenced. Switch the dereference and kfree. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Chris Mason <chris.mason@oracle.com> --- fs/btrfs/async-thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 7f88628a1a72e..6e4f6c50a120d 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -299,8 +299,8 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers) "btrfs-%s-%d", workers->name, workers->num_workers + i); if (IS_ERR(worker->task)) { - kfree(worker); ret = PTR_ERR(worker->task); + kfree(worker); goto fail; } -- GitLab From 68f5a38c3ea4ae9cc7a40f86ff6d6d031583d93a Mon Sep 17 00:00:00 2001 From: Hu Tao <cnhutao@gmail.com> Date: Thu, 2 Jul 2009 13:55:45 -0400 Subject: [PATCH 0558/1002] Btrfs: fix error message formatting Make an error msg look nicer by inserting a space between number and word. Signed-off-by: Hu Tao <hu.taoo@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Chris Mason <chris.mason@oracle.com> --- fs/btrfs/extent-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cd64cfc14f7f0..a5aca3997d426 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2696,7 +2696,7 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" ", %llu bytes_used, %llu bytes_reserved, " - "%llu bytes_pinned, %llu bytes_readonly, %llu may use" + "%llu bytes_pinned, %llu bytes_readonly, %llu may use " "%llu total\n", (unsigned long long)bytes, (unsigned long long)data_sinfo->bytes_delalloc, (unsigned long long)data_sinfo->bytes_used, -- GitLab From 14f4654cbd531d48651e005cf05907c14bddb193 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 17:58:19 +0200 Subject: [PATCH 0559/1002] perf_counter tools: Create new chain_for_each_child() iterator Iterating through children of a node in the callchain tree shows something that may be quite confusing at a first glance. The head is the children field of the parent and the list nodes are in the brothers field of the children. This is because the childs are linked to the parent as a list of "brothers" using the "children" list of the parent as a head: --------------- | Parent (head) |------------------------------------- --------------- | | | children | | | ----------- ----------- | | 1st child |---brother---| 2nd child |---brother----- ----------- ----------- This makes the following strange pattern often occuring: list_for_each_entry(child, &parent->children, brothers) { // do something with children } Abstract it to chain_for_each_child() to factorize and simplify this pattern. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246550301-8954-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/callchain.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 3dceabd9b5efa..3c4a91fea6223 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -16,6 +16,9 @@ #include "callchain.h" +#define chain_for_each_child(child, parent) \ + list_for_each_entry(child, &parent->children, brothers) + static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) @@ -46,7 +49,7 @@ void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) { struct callchain_node *child; - list_for_each_entry(child, &node->children, brothers) + chain_for_each_child(child, node) sort_chain_to_rbtree(rb_root, child); if (node->hit) @@ -77,7 +80,7 @@ create_child(struct callchain_node *parent, bool inherit_children) list_splice(&parent->children, &new->children); INIT_LIST_HEAD(&parent->children); - list_for_each_entry(next, &new->children, brothers) + chain_for_each_child(next, new) next->parent = new; } list_add_tail(&new->brothers, &parent->children); @@ -173,7 +176,7 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain, struct callchain_node *rnode; /* lookup in childrens */ - list_for_each_entry(rnode, &root->children, brothers) { + chain_for_each_child(rnode, root) { unsigned int ret = __append_chain(rnode, chain, start, syms); if (!ret) -- GitLab From 5a4b181721375700124513cdd9f97056e1c66675 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 17:58:20 +0200 Subject: [PATCH 0560/1002] perf_counter tools: Add new OPT_CALLBACK_DEFAULT option There is no predefined macro to create an option that can have a custom value or a default one if none is given. This patch provides a new helper OPT_CALLBACK_DEFAULT() which defines such kind of option. For example, considering an option -c, we want to get the default value in the following cases: perf command -c -d perf command -d -c And the foo value when it's given: perf command -c foo -d perf command -d -c foo That's also why PARSE_OPT_LASTARG_DEFAULT is extended here to support default values whatever the position of the option, not only in the end. Should it now be renamed to PARSE_OPT_ARG_DEFAULT ? Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: git@vger.kernel.org LKML-Reference: <1246550301-8954-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/parse-options.c | 3 ++- tools/perf/util/parse-options.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 9a897b7cce790..1bf67190c8200 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -20,7 +20,8 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, if (p->opt) { *arg = p->opt; p->opt = NULL; - } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) { + } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || + **(p->argv + 1) == '-')) { *arg = (const char *)opt->defval; } else if (p->argc > 1) { p->argc--; diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 15c8aba9c62e7..8aa3464c70905 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -104,6 +104,8 @@ struct option { { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } +#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } /* parse_options() will filter out the processed options and leave the * non-option argments in argv[]. -- GitLab From 4eb3e4788b8a5e220a0aeb590f88c28850726ebe Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 17:58:21 +0200 Subject: [PATCH 0561/1002] perf report: Add support for callchain graph output Currently, the printing of callchains is done in a single vertical level, this is the "flat" mode: 8.25% [k] copy_user_generic_string 4.19% copy_user_generic_string generic_file_aio_read do_sync_read vfs_read sys_pread64 system_call_fastpath pread64 This patch introduces a new "graph" mode which provides a hierarchical output of factorized paths recursively sorted: 8.25% [k] copy_user_generic_string | |--4.31%-- generic_file_aio_read | do_sync_read | vfs_read | | | |--4.19%-- sys_pread64 | | system_call_fastpath | | pread64 | | | --0.12%-- sys_read | system_call_fastpath | __read | |--3.24%-- generic_file_buffered_write | __generic_file_aio_write_nolock | generic_file_aio_write | do_sync_write | reiserfs_file_write | vfs_write | | | |--3.14%-- sys_pwrite64 | | system_call_fastpath | | __pwrite64 | | | --0.10%-- sys_write [...] The command line has then changed. By providing the -c option, the callchain will output in the flat mode by default. But you can override it: perf report -c graph or perf report -c flat You can also pass the abreviated mode: perf report -c g or perf report -c gra will both make use of the graph mode. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246550301-8954-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 141 ++++++++++++++++++++++++++++++++++-- tools/perf/util/callchain.c | 51 ++++++++++--- tools/perf/util/callchain.h | 11 ++- 3 files changed, 185 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b44476ca23988..0ca46386d9364 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -59,6 +59,7 @@ static regex_t parent_regex; static int exclude_other = 1; static int callchain; +static enum chain_mode callchain_mode; static u64 sample_type; @@ -787,8 +788,103 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) return cmp; } +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) +{ + int i; + size_t ret = 0; + + ret += fprintf(fp, "%s", " "); + + for (i = 0; i < depth; i++) + if (depth_mask & (1 << i)) + ret += fprintf(fp, "| "); + else + ret += fprintf(fp, " "); + + ret += fprintf(fp, "\n"); + + return ret; +} static size_t -callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) +ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, + int depth_mask, int count, u64 total_samples, + int hits) +{ + int i; + size_t ret = 0; + + ret += fprintf(fp, "%s", " "); + for (i = 0; i < depth; i++) { + if (depth_mask & (1 << i)) + ret += fprintf(fp, "|"); + else + ret += fprintf(fp, " "); + if (!count && i == depth - 1) { + double percent; + + percent = hits * 100.0 / total_samples; + ret += fprintf(fp, "--%2.2f%%-- ", percent); + } else + ret += fprintf(fp, "%s", " "); + } + if (chain->sym) + ret += fprintf(fp, "%s\n", chain->sym->name); + else + ret += fprintf(fp, "%p\n", (void *)(long)chain->ip); + + return ret; +} + +static size_t +callchain__fprintf_graph(FILE *fp, struct callchain_node *self, + u64 total_samples, int depth, int depth_mask) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + size_t ret = 0; + int i; + + node = rb_first(&self->rb_root); + while (node) { + child = rb_entry(node, struct callchain_node, rb_node); + + /* + * The depth mask manages the output of pipes that show + * the depth. We don't want to keep the pipes of the current + * level for the last child of this depth + */ + next = rb_next(node); + if (!next) + new_depth_mask &= ~(1 << (depth - 1)); + + /* + * But we keep the older depth mask for the line seperator + * to keep the level link until we reach the last child + */ + ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); + i = 0; + list_for_each_entry(chain, &child->val, list) { + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + ret += ipchain__fprintf_graph(fp, chain, depth, + new_depth_mask, i++, + total_samples, + child->cumul_hit); + } + ret += callchain__fprintf_graph(fp, child, total_samples, + depth + 1, + new_depth_mask | (1 << depth)); + node = next; + } + + return ret; +} + +static size_t +callchain__fprintf_flat(FILE *fp, struct callchain_node *self, + u64 total_samples) { struct callchain_list *chain; size_t ret = 0; @@ -796,7 +892,7 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) if (!self) return 0; - ret += callchain__fprintf(fp, self->parent, total_samples); + ret += callchain__fprintf_flat(fp, self->parent, total_samples); list_for_each_entry(chain, &self->val, list) { @@ -826,8 +922,13 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; - ret += fprintf(fp, " %6.2f%%\n", percent); - ret += callchain__fprintf(fp, chain, total_samples); + if (callchain_mode == FLAT) { + ret += fprintf(fp, " %6.2f%%\n", percent); + ret += callchain__fprintf_flat(fp, chain, total_samples); + } else if (callchain_mode == GRAPH) { + ret += callchain__fprintf_graph(fp, chain, + total_samples, 1, 1); + } ret += fprintf(fp, "\n"); rb_node = rb_next(rb_node); } @@ -1129,8 +1230,12 @@ static void output__insert_entry(struct hist_entry *he) struct rb_node *parent = NULL; struct hist_entry *iter; - if (callchain) - sort_chain_to_rbtree(&he->sorted_chain, &he->callchain); + if (callchain) { + if (callchain_mode == FLAT) + sort_chain_flat(&he->sorted_chain, &he->callchain); + else if (callchain_mode == GRAPH) + sort_chain_graph(&he->sorted_chain, &he->callchain); + } while (*p != NULL) { parent = *p; @@ -1702,6 +1807,26 @@ static int __cmd_report(void) return rc; } +static int +parse_callchain_opt(const struct option *opt __used, const char *arg, + int unset __used) +{ + callchain = 1; + + if (!arg) + return 0; + + if (!strncmp(arg, "graph", strlen(arg))) + callchain_mode = GRAPH; + + else if (!strncmp(arg, "flat", strlen(arg))) + callchain_mode = FLAT; + else + return -1; + + return 0; +} + static const char * const report_usage[] = { "perf report [<options>] <command>", NULL @@ -1725,7 +1850,9 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &exclude_other, "Only display entries with parent-match"), - OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), + OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type", + "Display callchains with output_type: flat, graph. " + "Default to flat", &parse_callchain_opt, "flat"), OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 3c4a91fea6223..a9873aafcd928 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -19,9 +19,9 @@ #define chain_for_each_child(child, parent) \ list_for_each_entry(child, &parent->children, brothers) - static void -rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) +rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, + enum chain_mode mode) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; @@ -31,10 +31,22 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) parent = *p; rnode = rb_entry(parent, struct callchain_node, rb_node); - if (rnode->hit < chain->hit) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; + switch (mode) { + case FLAT: + if (rnode->hit < chain->hit) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + break; + case GRAPH: + if (rnode->cumul_hit < chain->cumul_hit) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + break; + default: + break; + } } rb_link_node(&chain->rb_node, parent, p); @@ -45,15 +57,36 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) * Once we get every callchains from the stream, we can now * sort them by hit */ -void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) +void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node) { struct callchain_node *child; chain_for_each_child(child, node) - sort_chain_to_rbtree(rb_root, child); + sort_chain_flat(rb_root, child); if (node->hit) - rb_insert_callchain(rb_root, node); + rb_insert_callchain(rb_root, node, FLAT); +} + +static void __sort_chain_graph(struct callchain_node *node) +{ + struct callchain_node *child; + + node->rb_root = RB_ROOT; + node->cumul_hit = node->hit; + + chain_for_each_child(child, node) { + __sort_chain_graph(child); + rb_insert_callchain(&node->rb_root, child, GRAPH); + node->cumul_hit += child->cumul_hit; + } +} + +void +sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root) +{ + __sort_chain_graph(chain_root); + rb_root->rb_node = chain_root->rb_root.rb_node; } /* diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index e9bd5e882f38e..dfa56008d9ad0 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -6,15 +6,21 @@ #include <linux/rbtree.h> #include "symbol.h" +enum chain_mode { + FLAT, + GRAPH +}; struct callchain_node { struct callchain_node *parent; struct list_head brothers; struct list_head children; struct list_head val; - struct rb_node rb_node; + struct rb_node rb_node; /* to sort nodes in an rbtree */ + struct rb_root rb_root; /* sorted tree of children */ unsigned int val_nr; u64 hit; + u64 cumul_hit; /* hit + hits of children */ }; struct callchain_list { @@ -32,5 +38,6 @@ static inline void callchain_init(struct callchain_node *node) void append_chain(struct callchain_node *root, struct ip_callchain *chain, struct symbol **syms); -void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); +void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node); +void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node); #endif -- GitLab From 43644679a1e80f53e6e0155ab75b1093ba3c0365 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Thu, 2 Jul 2009 12:05:10 -0700 Subject: [PATCH 0562/1002] x86: fix power-of-2 round_up/round_down macros These macros had two bugs: - the type of the mask was not correctly expanded to the full size of the argument being expanded, resulting in possible loss of high bits when mixing types. - the alignment argument was evaluated twice, despite the macro looking like a fancy function (but it really does need to be a macro, since it works on arbitrary integer types) Noticed by Peter Anvin, and with a fix that is a modification of his suggestion (bug noticed by Yinghai Lu). Cc: Peter Anvin <hpa@zytor.com> Cc: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/include/asm/proto.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 49fb3ecf3bb34..621f56d731212 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h @@ -22,7 +22,14 @@ extern int reboot_force; long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); -#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1)) -#define round_down(x, y) ((x) & ~((y) - 1)) +/* + * This looks more complex than it should be. But we need to + * get the type for the ~ right in round_down (it needs to be + * as wide as the result!), and we want to evaluate the macro + * arguments just once each. + */ +#define __round_mask(x,y) ((__typeof__(x))((y)-1)) +#define round_up(x,y) ((((x)-1) | __round_mask(x,y))+1) +#define round_down(x,y) ((x) & ~__round_mask(x,y)) #endif /* _ASM_X86_PROTO_H */ -- GitLab From 7c5371c403abb29f01bc6cff6c5096abdf2dc524 Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Wed, 1 Jul 2009 12:32:18 -0700 Subject: [PATCH 0563/1002] x86: add boundary check for 32bit res before expand e820 resource to alignment fix hang with HIGHMEM_64G and 32bit resource. According to hpa and Linus, use (resource_size_t)-1 to fend off big ranges. Analyzed by hpa Reported-and-tested-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/kernel/e820.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 7271fa33d7913..c4ca89d9aaf46 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1383,6 +1383,8 @@ static unsigned long ram_alignment(resource_size_t pos) return 32*1024*1024; } +#define MAX_RESOURCE_SIZE ((resource_size_t)-1) + void __init e820_reserve_resources_late(void) { int i; @@ -1400,17 +1402,19 @@ void __init e820_reserve_resources_late(void) * avoid stolen RAM: */ for (i = 0; i < e820.nr_map; i++) { - struct e820entry *entry = &e820_saved.map[i]; - resource_size_t start, end; + struct e820entry *entry = &e820.map[i]; + u64 start, end; if (entry->type != E820_RAM) continue; start = entry->addr + entry->size; - end = round_up(start, ram_alignment(start)); - if (start == end) + end = round_up(start, ram_alignment(start)) - 1; + if (end > MAX_RESOURCE_SIZE) + end = MAX_RESOURCE_SIZE; + if (start >= end) continue; - reserve_region_with_split(&iomem_resource, start, - end - 1, "RAM buffer"); + reserve_region_with_split(&iomem_resource, start, end, + "RAM buffer"); } } -- GitLab From af2719415a5ceae06f2a6d33e78b555e64697fc8 Mon Sep 17 00:00:00 2001 From: Stefan Richter <stefanr@s5r6.in-berlin.de> Date: Tue, 30 Jun 2009 20:27:59 +0200 Subject: [PATCH 0564/1002] firewire: sbp2: add support for disks >2 TB (and 16 bytes long CDBs) Increase the command ORB data structure to transport up to 16 bytes long CDBs (instead of 12 bytes), and tell the SCSI mid layer about it. This is notably necessary for READ CAPACITY(16) and friends, i.e. support of large disks. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/firewire/sbp2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 2353643721c13..d27cb058da82e 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -200,6 +200,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) #define SBP2_RETRY_LIMIT 0xf /* 15 retries */ #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ +/* + * There is no transport protocol limit to the CDB length, but we implement + * a fixed length only. 16 bytes is enough for disks larger than 2 TB. + */ +#define SBP2_MAX_CDB_SIZE 16 + /* * The default maximum s/g segment size of a FireWire controller is * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to @@ -312,7 +318,7 @@ struct sbp2_command_orb { struct sbp2_pointer next; struct sbp2_pointer data_descriptor; __be32 misc; - u8 command_block[12]; + u8 command_block[SBP2_MAX_CDB_SIZE]; } request; struct scsi_cmnd *cmd; scsi_done_fn_t done; @@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) if (fw_device_enable_phys_dma(device) < 0) goto fail_shost_put; + shost->max_cmd_len = SBP2_MAX_CDB_SIZE; + if (scsi_add_host(shost, &unit->device) < 0) goto fail_shost_put; -- GitLab From ebbb16bffa646f853899ef3fdc0ac7abab888703 Mon Sep 17 00:00:00 2001 From: Stefan Richter <stefanr@s5r6.in-berlin.de> Date: Tue, 30 Jun 2009 20:28:31 +0200 Subject: [PATCH 0565/1002] ieee1394: sbp2: add support for disks >2 TB (and 16 bytes long CDBs) Increase the command ORB data structure to transport up to 16 bytes long CDBs (instead of 12 bytes), and tell the SCSI mid layer about it. This is notably necessary for READ CAPACITY(16) and friends, i.e. support of large disks. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/ieee1394/sbp2.c | 1 + drivers/ieee1394/sbp2.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index a51ab233342de..f599f49347394 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) } shost->hostdata[0] = (unsigned long)lu; + shost->max_cmd_len = SBP2_MAX_CDB_SIZE; if (!scsi_add_host(shost, &ud->device)) { lu->shost = shost; diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index c5036f1cc5b0d..64a3a66a8a396 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -24,6 +24,12 @@ #define SBP2_DEVICE_NAME "sbp2" +/* + * There is no transport protocol limit to the CDB length, but we implement + * a fixed length only. 16 bytes is enough for disks larger than 2 TB. + */ +#define SBP2_MAX_CDB_SIZE 16 + /* * SBP-2 specific definitions */ @@ -51,7 +57,7 @@ struct sbp2_command_orb { u32 data_descriptor_hi; u32 data_descriptor_lo; u32 misc; - u8 cdb[12]; + u8 cdb[SBP2_MAX_CDB_SIZE]; } __attribute__((packed)); #define SBP2_LOGIN_REQUEST 0x0 -- GitLab From c20ab37ef30f4a874cf27e84c12c73e584e6f5cc Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 20:14:33 +0200 Subject: [PATCH 0566/1002] perf_counter tools: Set the minimum percent for callchains to be displayed Callchains output may become a burden on a trace because even rarely hit site are exposed. This can be too much information. Let the user set a threshold as a minimum percent of hits using the new pattern for the -c option: -c mode,min_percent Example: $ perf report -s sym -c flat,4 8.25% [k] copy_user_generic_string 4.19% copy_user_generic_string generic_file_aio_read do_sync_read vfs_read sys_pread64 system_call_fastpath pread64 5.39% [k] search_by_key 4.63% 0x00000000009e0a 2.36% [k] memcpy_c [...] $ perf report -s sym -c graph,2 8.25% [k] copy_user_generic_string | |--4.31%-- generic_file_aio_read | do_sync_read | vfs_read | | | --4.19%-- sys_pread64 | system_call_fastpath | pread64 | --3.24%-- generic_file_buffered_write __generic_file_aio_write_nolock generic_file_aio_write do_sync_write reiserfs_file_write vfs_write | --3.14%-- sys_pwrite64 system_call_fastpath __pwrite64 5.39% [k] search_by_key | --2.23%-- reiserfs_update_sd_size 4.63% 0x00000000009e0a 2.36% [k] memcpy_c [...] You can also omit it and it will default to 0. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246558475-10624-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 45 ++++++++++++++++++++++++++++--------- tools/perf/util/callchain.c | 19 +++++++++------- tools/perf/util/callchain.h | 6 +++-- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0ca46386d9364..e8c98179fe457 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -60,6 +60,7 @@ static regex_t parent_regex; static int exclude_other = 1; static int callchain; static enum chain_mode callchain_mode; +static double callchain_min_percent = 0.0; static u64 sample_type; @@ -1224,7 +1225,7 @@ static void collapse__resort(void) static struct rb_root output_hists; -static void output__insert_entry(struct hist_entry *he) +static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits) { struct rb_node **p = &output_hists.rb_node; struct rb_node *parent = NULL; @@ -1232,9 +1233,11 @@ static void output__insert_entry(struct hist_entry *he) if (callchain) { if (callchain_mode == FLAT) - sort_chain_flat(&he->sorted_chain, &he->callchain); + sort_chain_flat(&he->sorted_chain, &he->callchain, + min_callchain_hits); else if (callchain_mode == GRAPH) - sort_chain_graph(&he->sorted_chain, &he->callchain); + sort_chain_graph(&he->sorted_chain, &he->callchain, + min_callchain_hits); } while (*p != NULL) { @@ -1251,11 +1254,14 @@ static void output__insert_entry(struct hist_entry *he) rb_insert_color(&he->rb_node, &output_hists); } -static void output__resort(void) +static void output__resort(u64 total_samples) { struct rb_node *next; struct hist_entry *n; struct rb_root *tree = &hist; + u64 min_callchain_hits; + + min_callchain_hits = total_samples * (callchain_min_percent / 100); if (sort__need_collapse) tree = &collapse_hists; @@ -1267,7 +1273,7 @@ static void output__resort(void) next = rb_next(&n->rb_node); rb_erase(&n->rb_node, tree); - output__insert_entry(n); + output__insert_entry(n, min_callchain_hits); } } @@ -1801,7 +1807,7 @@ static int __cmd_report(void) dsos__fprintf(stdout); collapse__resort(); - output__resort(); + output__resort(total); output__fprintf(stdout, total); return rc; @@ -1811,19 +1817,36 @@ static int parse_callchain_opt(const struct option *opt __used, const char *arg, int unset __used) { + char *tok; + char *endptr; + callchain = 1; if (!arg) return 0; - if (!strncmp(arg, "graph", strlen(arg))) + tok = strtok((char *)arg, ","); + if (!tok) + return -1; + + /* get the output mode */ + if (!strncmp(tok, "graph", strlen(arg))) callchain_mode = GRAPH; - else if (!strncmp(arg, "flat", strlen(arg))) + else if (!strncmp(tok, "flat", strlen(arg))) callchain_mode = FLAT; else return -1; + /* get the min percentage */ + tok = strtok(NULL, ","); + if (!tok) + return 0; + + callchain_min_percent = strtod(tok, &endptr); + if (tok == endptr) + return -1; + return 0; } @@ -1850,9 +1873,9 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &exclude_other, "Only display entries with parent-match"), - OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type", - "Display callchains with output_type: flat, graph. " - "Default to flat", &parse_callchain_opt, "flat"), + OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent", + "Display callchains using output_type and min percent threshold. " + "Default: flat,0", &parse_callchain_opt, "flat,100"), OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index a9873aafcd928..c9900fe6b8b41 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -57,18 +57,19 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, * Once we get every callchains from the stream, we can now * sort them by hit */ -void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node) +void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit) { struct callchain_node *child; chain_for_each_child(child, node) - sort_chain_flat(rb_root, child); + sort_chain_flat(rb_root, child, min_hit); - if (node->hit) + if (node->hit && node->hit >= min_hit) rb_insert_callchain(rb_root, node, FLAT); } -static void __sort_chain_graph(struct callchain_node *node) +static void __sort_chain_graph(struct callchain_node *node, u64 min_hit) { struct callchain_node *child; @@ -76,16 +77,18 @@ static void __sort_chain_graph(struct callchain_node *node) node->cumul_hit = node->hit; chain_for_each_child(child, node) { - __sort_chain_graph(child); - rb_insert_callchain(&node->rb_root, child, GRAPH); + __sort_chain_graph(child, min_hit); + if (child->cumul_hit >= min_hit) + rb_insert_callchain(&node->rb_root, child, GRAPH); node->cumul_hit += child->cumul_hit; } } void -sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root) +sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root, + u64 min_hit) { - __sort_chain_graph(chain_root); + __sort_chain_graph(chain_root, min_hit); rb_root->rb_node = chain_root->rb_root.rb_node; } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index dfa56008d9ad0..f3e4776e74300 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -38,6 +38,8 @@ static inline void callchain_init(struct callchain_node *node) void append_chain(struct callchain_node *root, struct ip_callchain *chain, struct symbol **syms); -void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node); -void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node); +void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit); +void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit); #endif -- GitLab From 1e11fd82d247e4e48a1d6c49402214434538d3fd Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 20:14:34 +0200 Subject: [PATCH 0567/1002] perf_counter tools: Provide helper to print percents color Among perf annotate, perf report and perf top, we can find the common colored printing of percents according to the following rules: High overhead = > 5%, colored in red Mid overhead = > 0.5%, colored in green Low overhead = < 0.5%, default color Factorize these multiple checks in a single function named percent_color_fprintf() and also provide a get_percent_color() for sites which print percentages and other things at the same time. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246558475-10624-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-annotate.c | 26 ++------------------------ tools/perf/builtin-report.c | 21 +++------------------ tools/perf/builtin-top.c | 15 +-------------- tools/perf/util/color.c | 27 +++++++++++++++++++++++++++ tools/perf/util/color.h | 5 +++++ 5 files changed, 38 insertions(+), 56 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 08ea6c5329d99..5f9eefecc5740 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -25,10 +25,6 @@ #define SHOW_USER 2 #define SHOW_HV 4 -#define MIN_GREEN 0.5 -#define MIN_RED 5.0 - - static char const *input_name = "perf.data"; static char *vmlinux = "vmlinux"; @@ -1047,24 +1043,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head) return 0; } -static char *get_color(double percent) -{ - char *color = PERF_COLOR_NORMAL; - - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (percent >= MIN_RED) - color = PERF_COLOR_RED; - else { - if (percent > MIN_GREEN) - color = PERF_COLOR_GREEN; - } - return color; -} - static int parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) { @@ -1126,7 +1104,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) } else if (sym->hist_sum) percent = 100.0 * hits / sym->hist_sum; - color = get_color(percent); + color = get_percent_color(percent); /* * Also color the filename and line if needed, with @@ -1262,7 +1240,7 @@ static void print_summary(char *filename) sym_ext = rb_entry(node, struct sym_ext, node); percent = sym_ext->percent; - color = get_color(percent); + color = get_percent_color(percent); path = sym_ext->path; color_fprintf(stdout, color, " %7.2f %s", percent, path); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e8c98179fe457..c9dbe33154973 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -947,25 +947,10 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) if (exclude_other && !self->parent) return 0; - if (total_samples) { - double percent = self->count * 100.0 / total_samples; - char *color = PERF_COLOR_NORMAL; - - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (percent >= 5.0) { - color = PERF_COLOR_RED; - } else { - if (percent >= 0.5) - color = PERF_COLOR_GREEN; - } - - ret = color_fprintf(fp, color, " %6.2f%%", + if (total_samples) + ret = percent_color_fprintf(fp, " %6.2f%%", (self->count * 100.0) / total_samples); - } else + else ret = fprintf(fp, "%12Ld ", self->count); list_for_each_entry(se, &hist_entry__sort_list, list) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index aa044ea1482bf..95d5c0ae375ad 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -239,7 +239,6 @@ static void print_sym_table(void) for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); struct symbol *sym = (struct symbol *)(syme + 1); - char *color = PERF_COLOR_NORMAL; double pcnt; if (++printed > print_entries || syme->snap_count < count_filter) @@ -248,24 +247,12 @@ static void print_sym_table(void) pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / sum_ksamples)); - /* - * We color high-overhead entries in red, mid-overhead - * entries in green - and keep the low overhead places - * normal: - */ - if (pcnt >= 5.0) { - color = PERF_COLOR_RED; - } else { - if (pcnt >= 0.5) - color = PERF_COLOR_GREEN; - } - if (nr_counters == 1) printf("%20.2f - ", syme->weight); else printf("%9.1f %10ld - ", syme->weight, syme->snap_count); - color_fprintf(stdout, color, "%4.1f%%", pcnt); + percent_color_fprintf(stdout, "%4.1f%%", pcnt); printf(" - %016llx : %s", sym->start, sym->name); if (sym->module) printf("\t[%s]", sym->module->name); diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 26f82318b86bb..90a044d1fe7df 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -242,4 +242,31 @@ int color_fwrite_lines(FILE *fp, const char *color, return 0; } +char *get_percent_color(double percent) +{ + char *color = PERF_COLOR_NORMAL; + + /* + * We color high-overhead entries in red, mid-overhead + * entries in green - and keep the low overhead places + * normal: + */ + if (percent >= MIN_RED) + color = PERF_COLOR_RED; + else { + if (percent > MIN_GREEN) + color = PERF_COLOR_GREEN; + } + return color; +} +int percent_color_fprintf(FILE *fp, const char *fmt, double percent) +{ + int r; + char *color; + + color = get_percent_color(percent); + r = color_fprintf(fp, color, fmt, percent); + + return r; +} diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index 5abfd379582b4..706cec50bd251 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -15,6 +15,9 @@ #define PERF_COLOR_CYAN "\033[36m" #define PERF_COLOR_BG_RED "\033[41m" +#define MIN_GREEN 0.5 +#define MIN_RED 5.0 + /* * This variable stores the value of color.ui */ @@ -32,5 +35,7 @@ void color_parse_mem(const char *value, int len, const char *var, char *dst); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); +int percent_color_fprintf(FILE *fp, const char *fmt, double percent); +char *get_percent_color(double percent); #endif /* COLOR_H */ -- GitLab From 24b57c6988c5791628c89a8838910991abc9cc1e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Thu, 2 Jul 2009 20:14:35 +0200 Subject: [PATCH 0568/1002] perf_counter tools: Display percents of hits in callchain with overhead colors This adds the use of colors to signal at a glance the important overhead thresholds in callchains hit rates. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246558475-10624-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c9dbe33154973..283773d91aa04 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -824,7 +824,7 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, double percent; percent = hits * 100.0 / total_samples; - ret += fprintf(fp, "--%2.2f%%-- ", percent); + ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); } else ret += fprintf(fp, "%s", " "); } @@ -924,7 +924,8 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; if (callchain_mode == FLAT) { - ret += fprintf(fp, " %6.2f%%\n", percent); + ret += percent_color_fprintf(fp, " %6.2f%%\n", + percent); ret += callchain__fprintf_flat(fp, chain, total_samples); } else if (callchain_mode == GRAPH) { ret += callchain__fprintf_graph(fp, chain, -- GitLab From bceb0f126f25184eaec3f3c8f00c92b0d899e5de Mon Sep 17 00:00:00 2001 From: Tilman Schmidt <tilman@imap.cc> Date: Wed, 1 Jul 2009 11:20:57 +0000 Subject: [PATCH 0569/1002] gigaset: accept connection establishment messages in any order ISDN connection setup failed if the "connection active" and "B channel up" messages from the device arrived in a different order than expected. Modify the state machine to accept them in any order. Impact: bugfix Signed-off-by: Tilman Schmidt <tilman@imap.cc> CC: stable <stable@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/isdn/gigaset/ev-layer.c | 44 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index ec5169604a6a9..2d91049571a4c 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -294,32 +294,33 @@ struct reply_t gigaset_tab_cid[] = {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ + {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, {RSP_OK, 607,607, -1, 608,-1}, - //{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, - {RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}}, - {RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}}, {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, - /* dialing */ - {RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */ - - /* connection established */ - {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 - {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 - - {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout + /* optional dialing responses */ + {EV_BC_OPEN, 650,650, -1, 651,-1}, + {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, + {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, + + /* connect */ + {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, + {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP}}, + {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, + {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP}}, + {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, /* remote hangup */ - {RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, - {RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, + {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, + {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, /* hangup */ @@ -358,7 +359,8 @@ struct reply_t gigaset_tab_cid[] = {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, - {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, + {EV_BC_OPEN, 750,750, -1, 751,-1}, + {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, /* B channel closed (general case) */ {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME @@ -876,12 +878,6 @@ static void bchannel_down(struct bc_state *bcs) static void bchannel_up(struct bc_state *bcs) { - if (!(bcs->chstate & CHS_D_UP)) { - dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__); - bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); - } - if (bcs->chstate & CHS_B_UP) { dev_notice(bcs->cs->dev, "%s: B channel already up\n", __func__); -- GitLab From c56bd0c39ce31e694b6f32223c15bdd582263a3f Mon Sep 17 00:00:00 2001 From: Tilman Schmidt <tilman@imap.cc> Date: Wed, 1 Jul 2009 11:20:57 +0000 Subject: [PATCH 0570/1002] gigaset: drop pointless check Drop a sanity check which doesn't serve any useful purpose anymore. Signed-off-by: Tilman Schmidt <tilman@imap.cc> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/isdn/gigaset/isocdata.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index db3a1e4cd4893..bed38fcc432b6 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -174,12 +174,6 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) pr_err("invalid size %d\n", size); return -EINVAL; } - src = iwb->read; - if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD || - (read < src && limit >= src))) { - pr_err("isoc write buffer frame reservation violated\n"); - return -EFAULT; - } #endif if (read < write) { -- GitLab From 98e31bb00983a5b6d638a31e4ff77e5ca1ccf93e Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke <dhananjay@netxen.com> Date: Wed, 1 Jul 2009 11:41:42 +0000 Subject: [PATCH 0571/1002] netxen: fix the version code macro Correct firmware encoding is 8 bit major, 8 bit minor and 16 bit subversion. Flash has sizes rightly set, but original driver submission messed it leaving 16 bit major and 8 bit subversion. Also fix a infinite loop when cut-thru file firmware is invalid. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/netxen/netxen_nic.h | 13 ++++++++++++- drivers/net/netxen/netxen_nic_init.c | 25 ++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 970cedeb5f37b..26afcb5658d46 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -60,7 +60,18 @@ #define _NETXEN_NIC_LINUX_SUBVERSION 30 #define NETXEN_NIC_LINUX_VERSIONID "4.0.30" -#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) +#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) +#define _major(v) (((v) >> 24) & 0xff) +#define _minor(v) (((v) >> 16) & 0xff) +#define _build(v) ((v) & 0xffff) + +/* version in image has weird encoding: + * 7:0 - major + * 15:8 - minor + * 31:16 - build (little endian) + */ +#define NETXEN_DECODE_VERSION(v) \ + NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16)) #define NETXEN_NUM_FLASH_SECTORS (64) #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 055bb61d6e777..7bdcbc67342f7 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -756,7 +756,7 @@ static int netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) { __le32 val; - u32 major, minor, build, ver, min_ver, bios; + u32 ver, min_ver, bios; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; @@ -768,21 +768,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) return -EINVAL; val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) min_ver = NETXEN_VERSION_CODE(4, 0, 216); else min_ver = NETXEN_VERSION_CODE(3, 4, 216); - ver = NETXEN_VERSION_CODE(major, minor, build); + ver = NETXEN_DECODE_VERSION(val); - if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { + if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { dev_err(&pdev->dev, "%s: firmware version %d.%d.%d unsupported\n", - fwname, major, minor, build); + fwname, _major(ver), _minor(ver), _build(ver)); return -EINVAL; } @@ -798,11 +795,12 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) if (netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&val)) return -EIO; - major = (__force u32)val & 0xff; - minor = ((__force u32)val >> 8) & 0xff; - build = (__force u32)val >> 16; - if (NETXEN_VERSION_CODE(major, minor, build) > ver) + val = NETXEN_DECODE_VERSION(val); + if (val > ver) { + dev_info(&pdev->dev, "%s: firmware is older than flash\n", + fwname); return -EINVAL; + } NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); return 0; @@ -830,6 +828,8 @@ void netxen_request_firmware(struct netxen_adapter *adapter) netxen_rom_fast_read(adapter, NX_FW_VERSION_OFFSET, (int *)&flashed_ver); + flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); + if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); if (capability & NX_PEG_TUNE_MN_PRESENT) { @@ -838,6 +838,9 @@ void netxen_request_firmware(struct netxen_adapter *adapter) } } + adapter->fw = NULL; + goto done; + request_fw: rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); if (rc != 0) { -- GitLab From 67c38fc61af930fa03b042932b6b14fbf8126222 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke <dhananjay@netxen.com> Date: Wed, 1 Jul 2009 11:41:43 +0000 Subject: [PATCH 0572/1002] netxen: avoid frequent firmware reset Restrict firmware reset to following cases - o chip rev is NX2031 (firmare doesn't support heartbit). o firmware is dead. o previous attempt to init firmware had failed. o we have got newer file firmware. This speeds up module load tremendously (by upto 8 sec), also avoids downtime for NCSI (management) pass-thru traffic. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/netxen/netxen_nic.h | 4 +- drivers/net/netxen/netxen_nic_hdr.h | 1 + drivers/net/netxen/netxen_nic_init.c | 86 +++++++++++++++++++++++++--- drivers/net/netxen/netxen_nic_main.c | 4 ++ 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 26afcb5658d46..e1cdba752e09d 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -625,6 +625,7 @@ struct netxen_new_user_info { #define NX_P2_MN_ROMIMAGE 0 #define NX_P3_CT_ROMIMAGE 1 #define NX_P3_MN_ROMIMAGE 2 +#define NX_FLASH_ROMIMAGE 3 #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ @@ -1254,7 +1255,7 @@ struct netxen_adapter { u32 resv3; u8 has_link_events; - u8 resv1; + u8 fw_type; u16 tx_context_id; u16 mtu; u16 is_up; @@ -1398,6 +1399,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_load_firmware(struct netxen_adapter *adapter); +int netxen_need_fw_reset(struct netxen_adapter *adapter); void netxen_request_firmware(struct netxen_adapter *adapter); void netxen_release_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 3cc047844af30..8241036756483 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -853,6 +853,7 @@ enum { #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) +#define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0)) #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 7bdcbc67342f7..b899bd51fcd87 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -683,12 +683,85 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) return 0; } +int +netxen_need_fw_reset(struct netxen_adapter *adapter) +{ + u32 count, old_count; + u32 val, version, major, minor, build; + int i, timeout; + u8 fw_type; + + /* NX2031 firmware doesn't support heartbit */ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 1; + + /* last attempt had failed */ + if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) + return 1; + + old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); + + for (i = 0; i < 10; i++) { + + timeout = msleep_interruptible(200); + if (timeout) { + NXWR32(adapter, CRB_CMDPEG_STATE, + PHAN_INITIALIZE_FAILED); + return -EINTR; + } + + count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); + if (count != old_count) + break; + } + + /* firmware is dead */ + if (count == old_count) + return 1; + + /* check if we have got newer or different file firmware */ + if (adapter->fw) { + + const struct firmware *fw = adapter->fw; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); + version = NETXEN_DECODE_VERSION(val); + + major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); + + if (version > NETXEN_VERSION_CODE(major, minor, build)) + return 1; + + if (version == NETXEN_VERSION_CODE(major, minor, build)) { + + val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); + fw_type = (val & 0x4) ? + NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE; + + if (adapter->fw_type != fw_type) + return 1; + } + } + + return 0; +} + +static char *fw_name[] = { + "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash", +}; + int netxen_load_firmware(struct netxen_adapter *adapter) { u64 *ptr64; u32 i, flashaddr, size; const struct firmware *fw = adapter->fw; + struct pci_dev *pdev = adapter->pdev; + + dev_info(&pdev->dev, "loading firmware from %s\n", + fw_name[adapter->fw_type]); if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); @@ -806,12 +879,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) return 0; } -static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; - void netxen_request_firmware(struct netxen_adapter *adapter) { u32 capability, flashed_ver; - int fw_type; + u8 fw_type; struct pci_dev *pdev = adapter->pdev; int rc = 0; @@ -838,6 +909,7 @@ void netxen_request_firmware(struct netxen_adapter *adapter) } } + fw_type = NX_FLASH_ROMIMAGE; adapter->fw = NULL; goto done; @@ -849,6 +921,7 @@ void netxen_request_firmware(struct netxen_adapter *adapter) goto request_mn; } + fw_type = NX_FLASH_ROMIMAGE; adapter->fw = NULL; goto done; } @@ -862,16 +935,13 @@ void netxen_request_firmware(struct netxen_adapter *adapter) goto request_mn; } + fw_type = NX_FLASH_ROMIMAGE; adapter->fw = NULL; goto done; } done: - if (adapter->fw) - dev_info(&pdev->dev, "loading firmware from file %s\n", - fw_name[fw_type]); - else - dev_info(&pdev->dev, "loading firmware from flash\n"); + adapter->fw_type = fw_type; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2919a2d12bf40..27539ddf94c4f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -718,6 +718,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) if (request_fw) netxen_request_firmware(adapter); + err = netxen_need_fw_reset(adapter); + if (err <= 0) + return err; + if (first_boot != 0x55555555) { NXWR32(adapter, CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); -- GitLab From 42caa074042e22f873c408a0d13be657b16192f1 Mon Sep 17 00:00:00 2001 From: Wade Farnsworth <wfarnsworth@mvista.com> Date: Wed, 1 Jul 2009 13:00:34 +0000 Subject: [PATCH 0573/1002] phylib: fixes for PHY_RESUMING state changes The PHY_HALTED state disables phydev->link, but the link will not be updated upon entering PHY_RESUMING. Add a call to phy_read_status() to update the link before entering PHY_RUNNING. If the link is not up at this point, enter the PHY_NOLINK state instead. Also, when transitioning from PHY_RESUMING to PHY_RUNNING, calls to netif_carrier_on() and phydev->adjust_link() are missing. Add the calls similar to the other transitions to PHY_RUNNING. Signed-off-by: Wade Farnsworth <wfarnsworth@mvista.com> Acked-by: Andy Fleming <afleming@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/phy/phy.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 61755cbd978e4..eda94fcd4065a 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -928,13 +928,32 @@ static void phy_state_machine(struct work_struct *work) * Otherwise, it's 0, and we're * still waiting for AN */ if (err > 0) { - phydev->state = PHY_RUNNING; + err = phy_read_status(phydev); + if (err) + break; + + if (phydev->link) { + phydev->state = PHY_RUNNING; + netif_carrier_on(phydev->attached_dev); + } else + phydev->state = PHY_NOLINK; + phydev->adjust_link(phydev->attached_dev); } else { phydev->state = PHY_AN; phydev->link_timeout = PHY_AN_TIMEOUT; } - } else - phydev->state = PHY_RUNNING; + } else { + err = phy_read_status(phydev); + if (err) + break; + + if (phydev->link) { + phydev->state = PHY_RUNNING; + netif_carrier_on(phydev->attached_dev); + } else + phydev->state = PHY_NOLINK; + phydev->adjust_link(phydev->attached_dev); + } break; } -- GitLab From 887b5ea3683ce04966e35fa2e5fe215bedcde73c Mon Sep 17 00:00:00 2001 From: Alexander Duyck <alexander.h.duyck@intel.com> Date: Wed, 1 Jul 2009 13:38:26 +0000 Subject: [PATCH 0574/1002] if_ether: add define for 1588 aka Timesync This patch adds ETH_P_1588 protocol ID define. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- include/linux/if_ether.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index ae3a1871413dd..70fdba2bbf716 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -78,6 +78,7 @@ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ -- GitLab From 15da4b1612d608a47e095439b3dd1d77ffe20e0c Mon Sep 17 00:00:00 2001 From: Abhishek Kulkarni <adkulkar@umail.iu.edu> Date: Wed, 1 Jul 2009 08:50:54 +0000 Subject: [PATCH 0575/1002] net/9p: Fix crash due to bad mount parameters. It is not safe to use match_int without checking the token type returned by match_token (especially when the token type returned is Opt_err and args is empty). Fix it. Signed-off-by: Abhishek Kulkarni <adkulkar@umail.iu.edu> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/9p/trans_fd.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a2a1814c7a8d6..8c2588e4edc0e 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) if (!*p) continue; token = match_token(p, tokens, args); - r = match_int(&args[0], &option); - if (r < 0) { - P9_DPRINTK(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; + if (token != Opt_err) { + r = match_int(&args[0], &option); + if (r < 0) { + P9_DPRINTK(P9_DEBUG_ERROR, + "integer field, but no integer?\n"); + ret = r; + continue; + } } switch (token) { case Opt_port: -- GitLab From 66d9e2102af038bcd3286a6efce83e1877e5997b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke <matthias@kaehlcke.net> Date: Sun, 28 Jun 2009 11:19:39 +0100 Subject: [PATCH 0576/1002] [ARM] 5576/1: Update kb9202_defconfig The default configuration file for the KwikByte kb9202 board was based on a 2.6.13-rc2 kernel and doesn't produce a bootable kernel. Update the configuration in order to produce a bootable image. Signed-off-by: Matthias Kaehlcke <matthias@kaehlcke.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/configs/kb9202_defconfig | 1158 +++++++++++++++++++++-------- 1 file changed, 842 insertions(+), 316 deletions(-) diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig index 8e74c66f239db..605a8462f1726 100644 --- a/arch/arm/configs/kb9202_defconfig +++ b/arch/arm/configs/kb9202_defconfig @@ -1,109 +1,246 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Sun Aug 14 19:26:59 2005 +# Linux kernel version: 2.6.30-rc8 +# Wed Jun 3 13:52:33 2009 # CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -CONFIG_UID16=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # -# CONFIG_EXPERIMENTAL is not set -CONFIG_CLEAN_COMPILE=y +CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -# CONFIG_KOBJECT_UEVENT is not set -# CONFIG_IKCONFIG is not set +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_TRACEPOINTS=y +CONFIG_MARKERS=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # -# Loadable module support +# IO Schedulers # -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set # # System Type # -# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set -CONFIG_ARCH_AT91=y +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# Atmel AT91 System-on-Chip +# CONFIG_ARCH_AT91RM9200=y +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y # -# AT91RM9200 Implementations +# AT91RM9200 Board Type # +# CONFIG_MACH_ONEARM is not set # CONFIG_ARCH_AT91RM9200DK is not set # CONFIG_MACH_AT91RM9200EK is not set # CONFIG_MACH_CSB337 is not set # CONFIG_MACH_CSB637 is not set # CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_ATEB9200 is not set CONFIG_MACH_KB9200=y +# CONFIG_MACH_PICOTUX2XX is not set +# CONFIG_MACH_KAFA is not set +# CONFIG_MACH_ECBAT91 is not set +# CONFIG_MACH_YL9200 is not set + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_TIMER_HZ=128 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set # # Processor Type # CONFIG_CPU_32=y CONFIG_CPU_ARM920T=y -CONFIG_CPU_32v4=y +CONFIG_CPU_32v4T=y CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y CONFIG_CPU_CACHE_V4WT=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y # # Processor Features @@ -112,23 +249,48 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_OUTER_CACHE is not set # # Bus support # -CONFIG_ISA_DMA_API=y - -# -# PCCARD (PCMCIA/CardBus) support -# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=128 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -137,8 +299,16 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x10000000 CONFIG_ZBOOT_ROM_BSS=0x20040000 -CONFIG_ZBOOT_ROM=y -CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" +# CONFIG_ZBOOT_ROM is not set +CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set # # Floating point emulation @@ -149,74 +319,251 @@ CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" # CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set # # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y -# CONFIG_ARTHUR is not set # # Power management options # # CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y # -# Device Drivers +# Networking options # +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # -# Generic Driver Options +# Network testing # -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -CONFIG_DEBUG_DRIVER=y +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # -# Memory Technology Devices (MTD) +# Device Drivers # -# CONFIG_MTD is not set # -# Parallel port support +# Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set +CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=y + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +CONFIG_ATMEL_TCLIB=y +CONFIG_ATMEL_TCB_CLKSRC=y +CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 +CONFIG_ATMEL_SSC=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set # -# IO Schedulers +# EEPROM support # -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -232,145 +579,87 @@ CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # -# CONFIG_SCSI_SPI_ATTRS is not set +CONFIG_SCSI_SPI_ATTRS=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_ARM_AT91_ETHER=y +# CONFIG_AX88796 is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set # -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices +# Wireless LAN # +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wireless LAN (non-hamradio) +# Enable WiMAX (Networking options) to see the WiMAX drivers # -# CONFIG_NET_RADIO is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set - -# -# ISDN subsystem -# +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_ISDN is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -380,7 +669,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -390,23 +678,25 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set # # Hardware I/O ports # -CONFIG_SERIO=y -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set # # Character devices # CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -419,215 +709,362 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set # -# IPMI +# Memory mapped GPIO expanders: # -# CONFIG_IPMI_HANDLER is not set # -# Watchdog Cards +# I2C GPIO expanders: # -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_AT91RM9200_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set # -# Ftape, the floppy tape device driver +# PCI GPIO expanders: # -# CONFIG_RAW_DRIVER is not set # -# TPM devices +# SPI GPIO expanders: # -# CONFIG_AT91_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set # -# I2C support +# Watchdog Device Drivers # -# CONFIG_I2C is not set +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91RM9200_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # -# Misc devices +# Sonics Silicon Backplane # +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set # -# Digital Video Broadcasting Devices +# Multimedia drivers # -# CONFIG_DVB is not set +# CONFIG_DAB is not set # # Graphics support # -# CONFIG_FB is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +CONFIG_FONT_MINI_4x6=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_LOGO is not set # CONFIG_SOUND is not set - -# -# USB support -# +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y -CONFIG_USB_DEBUG=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set # # USB Device Class drivers # -# CONFIG_USB_BLUETOOTH_TTY is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DEBUG=y -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_DPCM is not set - -# -# USB Input Devices -# -# CONFIG_USB_HID is not set # -# USB HID Boot Protocol drivers +# also be needed; see USB_STORAGE Help for more info # -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y # # USB Imaging devices # +# CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set # -# USB Multimedia devices +# USB port drivers # -# CONFIG_USB_DABUSB is not set +# CONFIG_USB_SERIAL is not set # -# Video4Linux support is needed for USB Multimedia device support +# USB Miscellaneous drivers # +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +# CONFIG_USB_GADGET is not set # -# USB Network Adapters +# OTG and related infrastructure # -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_MON is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set # -# USB port drivers +# MMC/SD/SDIO Card Drivers # +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set # -# USB Serial Converter support +# MMC/SD/SDIO Host Controller Drivers # -# CONFIG_USB_SERIAL is not set +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set # -# USB Miscellaneous drivers +# RTC interfaces # -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set # -# USB DSL modem support +# SPI RTC drivers # # -# USB Gadget Support +# Platform RTC drivers # -# CONFIG_USB_GADGET is not set +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# MMC/SD Card support +# on-CPU RTC drivers # -# CONFIG_MMC is not set +CONFIG_RTC_DRV_AT91RM9200=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems # CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # -# XFS support +# Caches # -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +# CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems @@ -639,7 +1076,7 @@ CONFIG_AUTOFS4_FS=y # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" @@ -649,53 +1086,70 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_UBIFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFSD is not set +# CONFIG_NFS_V4 is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y -CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -719,7 +1173,7 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -733,47 +1187,119 @@ CONFIG_NLS_ASCII=y # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set # # Security options # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set # CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# +# CONFIG_BINARY_PRINTF is not set # # Library routines # +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -- GitLab From b3d254955fb5797232ec329b136c363aa4fdaa05 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 24 Jun 2009 23:09:15 -0700 Subject: [PATCH 0577/1002] drm/i915: Adjust DisplayPort clocks to use 96MHz reference For some reason, the DP clocks were based off a 100MHz reference instead of the standard 96MHz reference. This caused some DP monitors to fail to lock to the signal. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_display.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 59de4951b6eec..508838ee31e02 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -816,24 +816,21 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, { intel_clock_t clock; if (target < 200000) { - clock.dot = 161670; - clock.p = 20; clock.p1 = 2; clock.p2 = 10; - clock.n = 0x01; - clock.m = 97; - clock.m1 = 0x10; - clock.m2 = 0x05; + clock.n = 2; + clock.m1 = 23; + clock.m2 = 8; } else { - clock.dot = 270000; - clock.p = 10; clock.p1 = 1; clock.p2 = 10; - clock.n = 0x02; - clock.m = 108; - clock.m1 = 0x12; - clock.m2 = 0x06; + clock.n = 1; + clock.m1 = 14; + clock.m2 = 2; } + clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2); + clock.p = (clock.p1 * clock.p2); + clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p; memcpy(best_clock, &clock, sizeof(intel_clock_t)); return true; } -- GitLab From 90eab5e09de20e8d991bbb11f6edfb573f906352 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Mon, 27 Apr 2009 08:29:12 -0400 Subject: [PATCH 0578/1002] parisc: wire up preadv/pwritev syscalls Generic compat handlers look appropriate, so use those. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/unistd.h | 4 +++- arch/parisc/kernel/syscall_table.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index ef26b009dc5da..a3c341976dc25 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -807,8 +807,10 @@ #define __NR_dup3 (__NR_Linux + 312) #define __NR_pipe2 (__NR_Linux + 313) #define __NR_inotify_init1 (__NR_Linux + 314) +#define __NR_preadv (__NR_Linux + 315) +#define __NR_pwritev (__NR_Linux + 316) -#define __NR_Linux_syscalls (__NR_inotify_init1 + 1) +#define __NR_Linux_syscalls (__NR_pwritev + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 03b9a01bc16cf..6a6296148e5d1 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -413,6 +413,8 @@ ENTRY_SAME(dup3) ENTRY_SAME(pipe2) ENTRY_SAME(inotify_init1) + ENTRY_COMP(preadv) + ENTRY_COMP(pwritev) /* Nothing yet */ -- GitLab From 17085a934592585bd878884dee04b850a367be10 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov <a.beregalov@gmail.com> Date: Fri, 3 Apr 2009 13:33:32 +0000 Subject: [PATCH 0579/1002] parisc: stifb: should depend on STI_CONSOLE Fix this build error when CONFIG_STI_CONSOLE is not set drivers/video/stifb.c:1337: undefined reference to `sti_get_rom' Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/video/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d6d65ef85f541..8afcf08eba986 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -616,6 +616,8 @@ config FB_STI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select STI_CONSOLE + select VT default y ---help--- STI refers to the HP "Standard Text Interface" which is a set of -- GitLab From 8d2d00ddeff2c2d1164d96e2d1b53e45ceb528c8 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov <a.beregalov@gmail.com> Date: Fri, 3 Apr 2009 12:08:54 +0000 Subject: [PATCH 0580/1002] parisc: ccio-dma: fix build failure without procfs Fix this build error when CONFIG_PROC_FS is not set: drivers/parisc/ccio-dma.c:1574: error: 'ccio_proc_info_fops' undeclared Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/parisc/ccio-dma.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 5d610cbcfe80c..0f0e0b919ef43 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1134,7 +1134,7 @@ static const struct file_operations ccio_proc_bitmap_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif +#endif /* CONFIG_PROC_FS */ /** * ccio_find_ioc - Find the ioc in the ioc_list @@ -1568,14 +1568,15 @@ static int __init ccio_probe(struct parisc_device *dev) /* if this fails, no I/O cards will work, so may as well bug */ BUG_ON(dev->dev.platform_data == NULL); HBA_DATA(dev->dev.platform_data)->iommu = ioc; - + +#ifdef CONFIG_PROC_FS if (ioc_count == 0) { proc_create(MODULE_NAME, 0, proc_runway_root, &ccio_proc_info_fops); proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root, &ccio_proc_bitmap_fops); } - +#endif ioc_count++; parisc_has_iommu(); -- GitLab From 071327ec9005e9a826d088d37021ed2c88e683f7 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov <a.beregalov@gmail.com> Date: Fri, 3 Apr 2009 01:49:22 +0000 Subject: [PATCH 0581/1002] parisc: remove CVS keywords Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com> Acked-by: Matthew Wilcox <willy@linux.intel.com> Acked-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/dma.h | 3 +-- arch/parisc/kernel/cache.c | 3 +-- arch/parisc/kernel/pci.c | 3 +-- arch/parisc/kernel/processor.c | 3 +-- arch/parisc/kernel/setup.c | 3 +-- arch/parisc/lib/checksum.c | 2 -- arch/parisc/mm/fault.c | 3 +-- 7 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/parisc/include/asm/dma.h b/arch/parisc/include/asm/dma.h index 31ad0f05af3d4..f7a18f9687034 100644 --- a/arch/parisc/include/asm/dma.h +++ b/arch/parisc/include/asm/dma.h @@ -1,5 +1,4 @@ -/* $Id: dma.h,v 1.2 1999/04/27 00:46:18 deller Exp $ - * linux/include/asm/dma.h: Defines for using and allocating dma channels. +/* asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. * High DMA channel support & info by Hannu Savolainen * and John Boyd, Nov. 1992. diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 837530ea32e78..f34082da009a5 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -1,5 +1,4 @@ -/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 6936386c9861a..f7064abc3bb6e 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -1,5 +1,4 @@ -/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index e09d0f7fb6b04..1ca69a808e38a 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -1,5 +1,4 @@ -/* $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $ - * +/* * Initial setup-routines for HP 9000 based hardware. * * Copyright (C) 1991, 1992, 1995 Linus Torvalds diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index 82131ca8e05c2..cb71f3dac9952 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -1,5 +1,4 @@ -/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $ - * +/* * Initial setup-routines for HP 9000 based hardware. * * Copyright (C) 1991, 1992, 1995 Linus Torvalds diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c index 462696d30d3bd..ae66d31f9ecf7 100644 --- a/arch/parisc/lib/checksum.c +++ b/arch/parisc/lib/checksum.c @@ -13,8 +13,6 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $ */ #include <linux/module.h> #include <linux/types.h> diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index bfb6dd6ab380c..c6afbfc957703 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -1,5 +1,4 @@ -/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. -- GitLab From 692c14a5931341a37e4fbfca5fa96751187a108f Mon Sep 17 00:00:00 2001 From: Bastian Blank <waldi@debian.org> Date: Sat, 4 Apr 2009 20:54:26 +0000 Subject: [PATCH 0582/1002] parisc: Remove casts from atomic macros The atomic operations on parisc are defined as macros. The macros includes casts which disallows the use of some syntax elements and produces error like this: net/phonet/pep.c: In function 'pipe_rcv_status': net/phonet/pep.c:262: error: lvalue required as left operand of assignment The patch removes this superfluous casts. Signed-off-by: Bastian Blank <waldi@debian.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/atomic.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 7eeaff9443603..82e9688f658c1 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -222,13 +222,13 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -#define atomic_add(i,v) ((void)(__atomic_add_return( ((int)(i)),(v)))) -#define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)(i)),(v)))) +#define atomic_add(i,v) ((void)(__atomic_add_return( (i),(v)))) +#define atomic_sub(i,v) ((void)(__atomic_add_return(-(i),(v)))) #define atomic_inc(v) ((void)(__atomic_add_return( 1,(v)))) #define atomic_dec(v) ((void)(__atomic_add_return( -1,(v)))) -#define atomic_add_return(i,v) (__atomic_add_return( ((int)(i)),(v))) -#define atomic_sub_return(i,v) (__atomic_add_return(-((int)(i)),(v))) +#define atomic_add_return(i,v) (__atomic_add_return( (i),(v))) +#define atomic_sub_return(i,v) (__atomic_add_return(-(i),(v))) #define atomic_inc_return(v) (__atomic_add_return( 1,(v))) #define atomic_dec_return(v) (__atomic_add_return( -1,(v))) -- GitLab From 4fb11781a044552dded5342e1a78cf92a74683db Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Sun, 5 Apr 2009 02:53:47 +0000 Subject: [PATCH 0583/1002] parisc: kill WARN in free_initmem when DEBUG_KERNEL Doing an IPI with local interrupts off triggers a warning. We don't need to be quite so ridiculously paranoid. Also, clean up a bit of the code a little. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/mm/init.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 4356ceb1e366d..6c5ea964647cf 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -370,34 +370,22 @@ static void __init setup_bootmem(void) void free_initmem(void) { - unsigned long addr, init_begin, init_end; - - printk(KERN_INFO "Freeing unused kernel memory: "); + unsigned long addr; + unsigned long init_begin = (unsigned long)__init_begin; + unsigned long init_end = (unsigned long)__init_end; #ifdef CONFIG_DEBUG_KERNEL /* Attempt to catch anyone trying to execute code here * by filling the page with BRK insns. - * - * If we disable interrupts for all CPUs, then IPI stops working. - * Kinda breaks the global cache flushing. */ - local_irq_disable(); - - memset(__init_begin, 0x00, - (unsigned long)__init_end - (unsigned long)__init_begin); - - flush_data_cache(); - asm volatile("sync" : : ); - flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end); - asm volatile("sync" : : ); - - local_irq_enable(); + memset(init_begin, 0x00, init_end - init_begin); + flush_icache_range(init_begin, init_end); #endif /* align __init_begin and __init_end to page size, ignoring linker script where we might have tried to save RAM */ - init_begin = PAGE_ALIGN((unsigned long)(__init_begin)); - init_end = PAGE_ALIGN((unsigned long)(__init_end)); + init_begin = PAGE_ALIGN(init_begin); + init_end = PAGE_ALIGN(init_end); for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); init_page_count(virt_to_page(addr)); @@ -409,7 +397,8 @@ void free_initmem(void) /* set up a new led state on systems shipped LED State panel */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE); - printk("%luk freed\n", (init_end - init_begin) >> 10); + printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n", + (init_end - init_begin) >> 10); } -- GitLab From 7d17e2763129ea307702fcdc91f6e9d114b65c2d Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Thu, 30 Apr 2009 21:39:45 +0000 Subject: [PATCH 0584/1002] parisc: fix ldcw inline assembler There are two reasons to expose the memory *a in the asm: 1) To prevent the compiler from discarding a preceeding write to *a, and 2) to prevent it from caching *a in a register over the asm. The change has had a few days testing with a SMP build of 2.6.22.19 running on a rp3440. This patch is about the correctness of the __ldcw() macro itself. The use of the macro should be confined to small inline functions to try to limit the effect of clobbering memory on GCC's optimization of loads and stores. Signed-off-by: Dave Anglin <dave.anglin@nrc-cnrc.gc.ca> Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/system.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h index ee80c920b464e..d91357bca5b4c 100644 --- a/arch/parisc/include/asm/system.h +++ b/arch/parisc/include/asm/system.h @@ -168,8 +168,8 @@ static inline void set_eiem(unsigned long val) /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ #define __ldcw(a) ({ \ unsigned __ret; \ - __asm__ __volatile__(__LDCW " 0(%1),%0" \ - : "=r" (__ret) : "r" (a)); \ + __asm__ __volatile__(__LDCW " 0(%2),%0" \ + : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ __ret; \ }) -- GitLab From fed99b1e86f5ff4f1b41e37264bb869da67d3174 Mon Sep 17 00:00:00 2001 From: Grant Grundler <grundler@parisc-linux.org> Date: Mon, 20 Apr 2009 04:28:22 +0000 Subject: [PATCH 0585/1002] parisc: advertise PCI devs after "assign_resources" Alex Chiang asked me why PARISC was calling pci_bus_add_devices() and pci_bus_assign_resources() in the opposite order from everyone else. No reason and I couldn't see any data dependency. Patch below applies cleanly to 2.6.30-rc2. Later, I suspected the code worked only because no drivers would be loaded/ready until much later in the system initialization sequence. Tested "LBA" code on J6000 (32-bit) and A500 (64-bit SMP) with 2.6.30-rc2. Not tested with any Dino controllers. Not tested with PCI-PCI Bridge (TBD). Reported-by: Alex Chiang <achiang@hp.com> Signed-off-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/parisc/dino.c | 10 +++++----- drivers/parisc/lba_pci.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 52ae0b1d470cc..d327c2dbf3e01 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -1019,22 +1019,22 @@ static int __init dino_probe(struct parisc_device *dev) ** It's not used to avoid chicken/egg problems ** with configuration accessor functions. */ - bus = pci_scan_bus_parented(&dev->dev, dino_current_bus, - &dino_cfg_ops, NULL); + dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev, + dino_current_bus, &dino_cfg_ops, NULL); + if(bus) { - pci_bus_add_devices(bus); /* This code *depends* on scanning being single threaded * if it isn't, this global bus number count will fail */ dino_current_bus = bus->subordinate + 1; pci_bus_assign_resources(bus); + pci_bus_add_devices(bus); } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", dev_name(&dev->dev), dino_current_bus); /* increment the bus number in case of duplicates */ dino_current_bus++; } - dino_dev->hba.hba_bus = bus; return 0; } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 59fbbf1283657..f2661e1255af1 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1509,10 +1509,6 @@ lba_driver_probe(struct parisc_device *dev) lba_bus = lba_dev->hba.hba_bus = pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, cfg_ops, NULL); - if (lba_bus) { - lba_next_bus = lba_bus->subordinate + 1; - pci_bus_add_devices(lba_bus); - } /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { @@ -1533,7 +1529,6 @@ lba_driver_probe(struct parisc_device *dev) } pci_enable_bridges(lba_bus); - /* ** Once PCI register ops has walked the bus, access to config ** space is restricted. Avoids master aborts on config cycles. @@ -1543,6 +1538,11 @@ lba_driver_probe(struct parisc_device *dev) lba_dev->flags |= LBA_FLAG_SKIP_PROBE; } + if (lba_bus) { + lba_next_bus = lba_bus->subordinate + 1; + pci_bus_add_devices(lba_bus); + } + /* Whew! Finally done! Tell services we got this one covered. */ return 0; } -- GitLab From 47b4150baa003fb83b93365f3eadd4c373e4fa6c Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Sat, 6 Jun 2009 21:54:28 +0000 Subject: [PATCH 0586/1002] parisc: fix irq compile bugs in arch/parisc/kernel/irq.c Fix miscompilation in arch/parisc/kernel/irq.c: 123: warning: passing arg 1 of `cpumask_setall' from incompatible pointer type 141: warning: passing arg 1 of `cpumask_copy' from incompatible pointer type 300: warning: passing arg 1 of `cpumask_copy' from incompatible pointer type 357: warning: passing arg 2 of `cpumask_copy' from incompatible pointer type Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 8007f1e657298..639451c50e474 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) if (CHECK_IRQ_PER_CPU(irq)) { /* Bad linux design decision. The mask has already * been set; we must reset it */ - cpumask_setall(&irq_desc[irq].affinity); + cpumask_setall(irq_desc[irq].affinity); return -EINVAL; } @@ -138,7 +138,7 @@ static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) if (cpu_dest < 0) return -1; - cpumask_copy(&irq_desc[irq].affinity, dest); + cpumask_copy(irq_desc[irq].affinity, dest); return 0; } @@ -299,7 +299,7 @@ int txn_alloc_irq(unsigned int bits_wide) unsigned long txn_affinity_addr(unsigned int irq, int cpu) { #ifdef CONFIG_SMP - cpumask_copy(&irq_desc[irq].affinity, cpumask_of(cpu)); + cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu)); #endif return per_cpu(cpu_data, cpu).txn_addr; @@ -356,7 +356,7 @@ void do_cpu_irq_mask(struct pt_regs *regs) irq = eirr_to_irq(eirr_val); #ifdef CONFIG_SMP - cpumask_copy(&dest, &irq_desc[irq].affinity); + cpumask_copy(&dest, irq_desc[irq].affinity); if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) && !cpu_isset(smp_processor_id(), dest)) { int cpu = first_cpu(dest); -- GitLab From dfe07565021959f0f646e9e775810c1bfbe0f6d6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner <tglx@linutronix.de> Date: Wed, 10 Jun 2009 19:56:04 +0000 Subject: [PATCH 0587/1002] parisc: remove obsolete hw_interrupt_type The defines and typedefs (hw_interrupt_type, no_irq_type, irq_desc_t) have been kept around for migration reasons. After more than two years it's time to remove them finally. This patch cleans up one of the remaining users. When all such patches hit mainline we can remove the defines and typedefs finally. Impact: cleanup Convert the last remaining users to struct irq_chip and remove the define. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/irq.c | 2 +- drivers/parisc/dino.c | 2 +- drivers/parisc/eisa.c | 2 +- drivers/parisc/gsc.c | 4 ++-- drivers/parisc/gsc.h | 2 +- drivers/parisc/iosapic.c | 2 +- drivers/parisc/superio.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 639451c50e474..330f536a93247 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -144,7 +144,7 @@ static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) } #endif -static struct hw_interrupt_type cpu_interrupt_type = { +static struct irq_chip cpu_interrupt_type = { .typename = "CPU", .startup = cpu_startup_irq, .shutdown = cpu_disable_irq, diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d327c2dbf3e01..c590974e9815c 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -353,7 +353,7 @@ static unsigned int dino_startup_irq(unsigned int irq) return 0; } -static struct hw_interrupt_type dino_interrupt_type = { +static struct irq_chip dino_interrupt_type = { .typename = "GSC-PCI", .startup = dino_startup_irq, .shutdown = dino_disable_irq, diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 5b89f404e6688..51220749cb656 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -188,7 +188,7 @@ static unsigned int eisa_startup_irq(unsigned int irq) return 0; } -static struct hw_interrupt_type eisa_interrupt_type = { +static struct irq_chip eisa_interrupt_type = { .typename = "EISA", .startup = eisa_startup_irq, .shutdown = eisa_disable_irq, diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index d336329176962..647adc9f85adf 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -148,7 +148,7 @@ static unsigned int gsc_asic_startup_irq(unsigned int irq) return 0; } -static struct hw_interrupt_type gsc_asic_interrupt_type = { +static struct irq_chip gsc_asic_interrupt_type = { .typename = "GSC-ASIC", .startup = gsc_asic_startup_irq, .shutdown = gsc_asic_disable_irq, @@ -158,7 +158,7 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = { .end = no_end_irq, }; -int gsc_assign_irq(struct hw_interrupt_type *type, void *data) +int gsc_assign_irq(struct irq_chip *type, void *data) { static int irq = GSC_IRQ_BASE; struct irq_desc *desc; diff --git a/drivers/parisc/gsc.h b/drivers/parisc/gsc.h index 762a1babad604..b9d7bfb68e24d 100644 --- a/drivers/parisc/gsc.h +++ b/drivers/parisc/gsc.h @@ -38,7 +38,7 @@ struct gsc_asic { int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic); int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */ int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */ -int gsc_assign_irq(struct hw_interrupt_type *type, void *data); +int gsc_assign_irq(struct irq_chip *type, void *data); int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit); void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose)(struct parisc_device *child, void *ctrl)); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 4a9cc92d4d186..88e333553212c 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -729,7 +729,7 @@ static int iosapic_set_affinity_irq(unsigned int irq, } #endif -static struct hw_interrupt_type iosapic_interrupt_type = { +static struct irq_chip iosapic_interrupt_type = { .typename = "IO-SAPIC-level", .startup = iosapic_startup_irq, .shutdown = iosapic_disable_irq, diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 33e5ade774ca0..589bd635e50fe 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -325,7 +325,7 @@ static unsigned int superio_startup_irq(unsigned int irq) return 0; } -static struct hw_interrupt_type superio_interrupt_type = { +static struct irq_chip superio_interrupt_type = { .typename = SUPERIO, .startup = superio_startup_irq, .shutdown = superio_disable_irq, -- GitLab From e9b2601073aa57ffde7259afbe86f405060058e3 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov <a.beregalov@gmail.com> Date: Mon, 6 Apr 2009 09:29:58 +0000 Subject: [PATCH 0588/1002] parisc: decode_exc.c should include kernel.h Fix this build error: arch/parisc/math-emu/decode_exc.c:351: undefined reference to `printk' Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/math-emu/decode_exc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c index 66c8a9f6a27eb..3ca1c61492182 100644 --- a/arch/parisc/math-emu/decode_exc.c +++ b/arch/parisc/math-emu/decode_exc.c @@ -40,7 +40,7 @@ * END_DESC */ - +#include <linux/kernel.h> #include "float.h" #include "sgl_float.h" #include "dbl_float.h" -- GitLab From ebc30a0f67a4d6a9470556f4311478b3b04c2b1f Mon Sep 17 00:00:00 2001 From: Coly Li <coly.li@suse.de> Date: Thu, 30 Apr 2009 22:43:46 +0000 Subject: [PATCH 0589/1002] parisc: add parameter to read_cr16() This patch modifies parameter of au1x_counter1_read() from 'void' to 'struct clocksource *cs', which fixes compile warning for incompatible parameter type. Signed-off-by: Coly Li <coly.li@suse.de> Signed-off-by: Helge Deller <deller@gmx.de> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index d4dd05674c623..d97d07f47a553 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -173,7 +173,7 @@ EXPORT_SYMBOL(profile_pc); /* clock source code */ -static cycle_t read_cr16(void) +static cycle_t read_cr16(struct clocksource *cs) { return get_cycles(); } -- GitLab From e957f608f321a97a60d065bccd01949590eef52e Mon Sep 17 00:00:00 2001 From: Grant Grundler <grundler@parisc-linux.org> Date: Tue, 23 Jun 2009 11:03:11 -0400 Subject: [PATCH 0590/1002] parisc: Fix gcc 4.4 warning in lba_pci.c gcc 4.4 warns about: drivers/parisc/lba_pci.c: In function 'lba_pat_resources': drivers/parisc/lba_pci.c:1099: warning: the frame size of 8280 bytes is larger than 4096 bytes The problem is we declare two large structures on the stack. They don't need to be on the stack since they are only used during LBA initialization (which is serialized). Moving to be "static". Signed-off-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/parisc/lba_pci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index f2661e1255af1..ede614616f8ef 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -980,28 +980,38 @@ static void lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { unsigned long bytecnt; - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ - pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ long io_count; long status; /* PDC return status */ long pa_count; + pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ + pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ int i; + pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); + if (!pa_pdc_cell) + return; + + io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); + if (!pa_pdc_cell) { + kfree(pa_pdc_cell); + return; + } + /* return cell module (IO view) */ status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, - PA_VIEW, & pa_pdc_cell); - pa_count = pa_pdc_cell.mod[1]; + PA_VIEW, pa_pdc_cell); + pa_count = pa_pdc_cell->mod[1]; status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, - IO_VIEW, &io_pdc_cell); - io_count = io_pdc_cell.mod[1]; + IO_VIEW, io_pdc_cell); + io_count = io_pdc_cell->mod[1]; /* We've already done this once for device discovery...*/ if (status != PDC_OK) { panic("pdc_pat_cell_module() call failed for LBA!\n"); } - if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { + if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); } @@ -1016,8 +1026,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) } *p, *io; struct resource *r; - p = (void *) &(pa_pdc_cell.mod[2+i*3]); - io = (void *) &(io_pdc_cell.mod[2+i*3]); + p = (void *) &(pa_pdc_cell->mod[2+i*3]); + io = (void *) &(io_pdc_cell->mod[2+i*3]); /* Convert the PAT range data to PCI "struct resource" */ switch(p->type & 0xff) { @@ -1096,6 +1106,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) break; } } + + kfree(pa_pdc_cell); + kfree(io_pdc_cell); } #else /* keep compiler from complaining about missing declarations */ -- GitLab From 87451d850c895470a122308086069b7c326c914b Mon Sep 17 00:00:00 2001 From: Randolph Chung <randolph@tausq.org> Date: Tue, 23 Jun 2009 14:53:26 +0000 Subject: [PATCH 0591/1002] parisc: fix mismatched parenthesis in memcpy.c >>>> I think this is what was intended? Note that this patch may affect >>>> profiling. >>> it really should be >>> >>> - if (likely(t1 & (sizeof(unsigned int)-1)) == 0) { >>> + if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) { >>> >>> randolph Reported-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: Randolph Chung <tausq@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/lib/memcpy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index bbda909c866e5..abf41f4632a9f 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -405,7 +405,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) unaligned_copy: /* possibly we are aligned on a word, but not on a double... */ - if (likely(t1 & (sizeof(unsigned int)-1)) == 0) { + if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) { t2 = src & (sizeof(unsigned int) - 1); if (unlikely(t2 != 0)) { -- GitLab From 84be31be3727d11b2a91781306b642e801c5a379 Mon Sep 17 00:00:00 2001 From: Grant Grundler <grundler@parisc-linux.org> Date: Mon, 1 Jun 2009 00:20:23 +0000 Subject: [PATCH 0592/1002] parisc: fix "delay!" timer handling Rewrote timer_interrupt() to properly handle the "delayed!" case. If we used floating point math to compute the number of ticks that had elapsed since the last timer interrupt, it could take up to 12K cycles (emperical!) to handle the interrupt. Existing code assumed it would never take more than 8k cycles. We end up programming Interval Timer to a value less than "current" cycle counter. Thus have to wait until Interval Timer "wrapped" and would then get the "delayed!" printk that I moved below. Since we don't really know what the upper limit is, I prefer to read CR16 again after we've programmed it to make sure we won't have to wait for CR16 to wrap. Further, the printk was between reading CR16 (cycle couner) and writing CR16 (the interval timer). This would cause us to continue to set the interval timer to a value that was "behind" the cycle counter. Rinse and repeat. So no printk's between reading CR16 and setting next interval timer. Tested on A500 (550 Mhz PA8600). Signed-off-by: Grant Grundler <grundler@parisc-linux.org> Tested-by: Kyle McMartin <kyle@mcmartin.ca> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> ---- Kyle, Helge, and other parisc's, Please test on 32-bit before committing. I think I have it right but recognize I might not. TODO: I wanted to use "do_div()" in order to get both remainder and value back with one division op. That should help with the latency alot but can be applied seperately from this patch. thanks, grant --- arch/parisc/kernel/time.c | 88 +++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index d97d07f47a553..a79c6f9e7e2c4 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -56,9 +56,9 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */ */ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) { - unsigned long now; + unsigned long now, now2; unsigned long next_tick; - unsigned long cycles_elapsed, ticks_elapsed; + unsigned long cycles_elapsed, ticks_elapsed = 1; unsigned long cycles_remainder; unsigned int cpu = smp_processor_id(); struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); @@ -71,44 +71,24 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) /* Initialize next_tick to the expected tick time. */ next_tick = cpuinfo->it_value; - /* Get current interval timer. - * CR16 reads as 64 bits in CPU wide mode. - * CR16 reads as 32 bits in CPU narrow mode. - */ + /* Get current cycle counter (Control Register 16). */ now = mfctl(16); cycles_elapsed = now - next_tick; - if ((cycles_elapsed >> 5) < cpt) { + if ((cycles_elapsed >> 6) < cpt) { /* use "cheap" math (add/subtract) instead * of the more expensive div/mul method */ cycles_remainder = cycles_elapsed; - ticks_elapsed = 1; while (cycles_remainder > cpt) { cycles_remainder -= cpt; ticks_elapsed++; } } else { + /* TODO: Reduce this to one fdiv op */ cycles_remainder = cycles_elapsed % cpt; - ticks_elapsed = 1 + cycles_elapsed / cpt; - } - - /* Can we differentiate between "early CR16" (aka Scenario 1) and - * "long delay" (aka Scenario 3)? I don't think so. - * - * We expected timer_interrupt to be delivered at least a few hundred - * cycles after the IT fires. But it's arbitrary how much time passes - * before we call it "late". I've picked one second. - */ - if (unlikely(ticks_elapsed > HZ)) { - /* Scenario 3: very long delay? bad in any case */ - printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" - " cycles %lX rem %lX " - " next/now %lX/%lX\n", - cpu, - cycles_elapsed, cycles_remainder, - next_tick, now ); + ticks_elapsed += cycles_elapsed / cpt; } /* convert from "division remainder" to "remainder of clock tick" */ @@ -122,18 +102,56 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) cpuinfo->it_value = next_tick; - /* Skip one clocktick on purpose if we are likely to miss next_tick. - * We want to avoid the new next_tick being less than CR16. - * If that happened, itimer wouldn't fire until CR16 wrapped. - * We'll catch the tick we missed on the tick after that. + /* Program the IT when to deliver the next interrupt. + * Only bottom 32-bits of next_tick are writable in CR16! */ - if (!(cycles_remainder >> 13)) - next_tick += cpt; - - /* Program the IT when to deliver the next interrupt. */ - /* Only bottom 32-bits of next_tick are written to cr16. */ mtctl(next_tick, 16); + /* Skip one clocktick on purpose if we missed next_tick. + * The new CR16 must be "later" than current CR16 otherwise + * itimer would not fire until CR16 wrapped - e.g 4 seconds + * later on a 1Ghz processor. We'll account for the missed + * tick on the next timer interrupt. + * + * "next_tick - now" will always give the difference regardless + * if one or the other wrapped. If "now" is "bigger" we'll end up + * with a very large unsigned number. + */ + now2 = mfctl(16); + if (next_tick - now2 > cpt) + mtctl(next_tick+cpt, 16); + +#if 1 +/* + * GGG: DEBUG code for how many cycles programming CR16 used. + */ + if (unlikely(now2 - now > 0x3000)) /* 12K cycles */ + printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!" + " cyc %lX rem %lX " + " next/now %lX/%lX\n", + cpu, now2 - now, cycles_elapsed, cycles_remainder, + next_tick, now ); +#endif + + /* Can we differentiate between "early CR16" (aka Scenario 1) and + * "long delay" (aka Scenario 3)? I don't think so. + * + * Timer_interrupt will be delivered at least a few hundred cycles + * after the IT fires. But it's arbitrary how much time passes + * before we call it "late". I've picked one second. + * + * It's important NO printk's are between reading CR16 and + * setting up the next value. May introduce huge variance. + */ + if (unlikely(ticks_elapsed > HZ)) { + /* Scenario 3: very long delay? bad in any case */ + printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" + " cycles %lX rem %lX " + " next/now %lX/%lX\n", + cpu, + cycles_elapsed, cycles_remainder, + next_tick, now ); + } /* Done mucking with unreliable delivery of interrupts. * Go do system house keeping. -- GitLab From e82a3b75127188f20c7780bec580e148beb29da7 Mon Sep 17 00:00:00 2001 From: Helge Deller <deller@gmx.de> Date: Tue, 16 Jun 2009 20:51:48 +0000 Subject: [PATCH 0593/1002] parisc: ensure broadcast tlb purge runs single threaded The TLB flushing functions on hppa, which causes PxTLB broadcasts on the system bus, needs to be protected by irq-safe spinlocks to avoid irq handlers to deadlock the kernel. The deadlocks only happened during I/O intensive loads and triggered pretty seldom, which is why this bug went so long unnoticed. Signed-off-by: Helge Deller <deller@gmx.de> [edited to use spin_lock_irqsave on UP as well since we'd been locking there all this time anyway, --kyle] Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/tlbflush.h | 14 +++++++------- arch/parisc/kernel/cache.c | 23 +++++++++++++++-------- arch/parisc/kernel/pci-dma.c | 12 ++++++++---- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 1f6fd4fc05b91..8f1a8100bf2df 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h @@ -12,14 +12,12 @@ * N class systems, only one PxTLB inter processor broadcast can be * active at any one time on the Merced bus. This tlb purge * synchronisation is fairly lightweight and harmless so we activate - * it on all SMP systems not just the N class. We also need to have - * preemption disabled on uniprocessor machines, and spin_lock does that - * nicely. + * it on all systems not just the N class. */ extern spinlock_t pa_tlb_lock; -#define purge_tlb_start(x) spin_lock(&pa_tlb_lock) -#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock) +#define purge_tlb_start(flags) spin_lock_irqsave(&pa_tlb_lock, flags) +#define purge_tlb_end(flags) spin_unlock_irqrestore(&pa_tlb_lock, flags) extern void flush_tlb_all(void); extern void flush_tlb_all_local(void *); @@ -63,14 +61,16 @@ static inline void flush_tlb_mm(struct mm_struct *mm) static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { + unsigned long flags; + /* For one page, it's not worth testing the split_tlb variable */ mb(); mtsp(vma->vm_mm->context,1); - purge_tlb_start(); + purge_tlb_start(flags); pdtlb(addr); pitlb(addr); - purge_tlb_end(); + purge_tlb_end(flags); } void __flush_tlb_range(unsigned long sid, diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index f34082da009a5..b6ed34de14e15 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -397,12 +397,13 @@ EXPORT_SYMBOL(flush_kernel_icache_range_asm); void clear_user_page_asm(void *page, unsigned long vaddr) { + unsigned long flags; /* This function is implemented in assembly in pacache.S */ extern void __clear_user_page_asm(void *page, unsigned long vaddr); - purge_tlb_start(); + purge_tlb_start(flags); __clear_user_page_asm(page, vaddr); - purge_tlb_end(); + purge_tlb_end(flags); } #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ @@ -443,20 +444,24 @@ extern void clear_user_page_asm(void *page, unsigned long vaddr); void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { + unsigned long flags; + purge_kernel_dcache_page((unsigned long)page); - purge_tlb_start(); + purge_tlb_start(flags); pdtlb_kernel(page); - purge_tlb_end(); + purge_tlb_end(flags); clear_user_page_asm(page, vaddr); } EXPORT_SYMBOL(clear_user_page); void flush_kernel_dcache_page_addr(void *addr) { + unsigned long flags; + flush_kernel_dcache_page_asm(addr); - purge_tlb_start(); + purge_tlb_start(flags); pdtlb_kernel(addr); - purge_tlb_end(); + purge_tlb_end(flags); } EXPORT_SYMBOL(flush_kernel_dcache_page_addr); @@ -489,8 +494,10 @@ void __flush_tlb_range(unsigned long sid, unsigned long start, if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ flush_tlb_all(); else { + unsigned long flags; + mtsp(sid, 1); - purge_tlb_start(); + purge_tlb_start(flags); if (split_tlb) { while (npages--) { pdtlb(start); @@ -503,7 +510,7 @@ void __flush_tlb_range(unsigned long sid, unsigned long start, start += PAGE_SIZE; } } - purge_tlb_end(); + purge_tlb_end(flags); } } diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 7d927eac932b9..c07f618ff7da9 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -90,12 +90,14 @@ static inline int map_pte_uncached(pte_t * pte, if (end > PMD_SIZE) end = PMD_SIZE; do { + unsigned long flags; + if (!pte_none(*pte)) printk(KERN_ERR "map_pte_uncached: page already exists\n"); set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); - purge_tlb_start(); + purge_tlb_start(flags); pdtlb_kernel(orig_vaddr); - purge_tlb_end(); + purge_tlb_end(flags); vaddr += PAGE_SIZE; orig_vaddr += PAGE_SIZE; (*paddr_ptr) += PAGE_SIZE; @@ -168,11 +170,13 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr, if (end > PMD_SIZE) end = PMD_SIZE; do { + unsigned long flags; pte_t page = *pte; + pte_clear(&init_mm, vaddr, pte); - purge_tlb_start(); + purge_tlb_start(flags); pdtlb_kernel(orig_vaddr); - purge_tlb_end(); + purge_tlb_end(flags); vaddr += PAGE_SIZE; orig_vaddr += PAGE_SIZE; pte++; -- GitLab From 4435607e986c792a8753f8850b570fdd80b21b10 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 11:40:37 -0400 Subject: [PATCH 0594/1002] parisc: wire up rt_tgsigqueueinfo Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/unistd.h | 3 ++- arch/parisc/kernel/syscall_table.S | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index a3c341976dc25..4e2aa0d149650 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -809,8 +809,9 @@ #define __NR_inotify_init1 (__NR_Linux + 314) #define __NR_preadv (__NR_Linux + 315) #define __NR_pwritev (__NR_Linux + 316) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317) -#define __NR_Linux_syscalls (__NR_pwritev + 1) +#define __NR_Linux_syscalls (__NR_rt_tgsigqueueinfo + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 6a6296148e5d1..83f8959ff6504 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -413,8 +413,9 @@ ENTRY_SAME(dup3) ENTRY_SAME(pipe2) ENTRY_SAME(inotify_init1) - ENTRY_COMP(preadv) + ENTRY_COMP(preadv) /* 315 */ ENTRY_COMP(pwritev) + ENTRY_COMP(rt_tgsigqueueinfo) /* Nothing yet */ -- GitLab From c3301ab4fb64cf84321d35a8e94f68c94c816dc1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig <hch@lst.de> Date: Tue, 23 Jun 2009 11:47:07 -0400 Subject: [PATCH 0595/1002] parisc: remove dead code from sys_parisc32.c Unless I'm totally missing something get_fd_set32/set_fd_set32 are completely unused. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/sys_parisc32.c | 62 ------------------------------- 1 file changed, 62 deletions(-) diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 1adb40c816696..92a0acaa0d121 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -174,68 +174,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid, return ret; } -/*** copied from mips64 ***/ -/* - * Ooo, nasty. We need here to frob 32-bit unsigned longs to - * 64-bit unsigned longs. - */ - -static inline int -get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - if (ufdset) { - unsigned long odd; - - if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32))) - return -EFAULT; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - __get_user(l, ufdset); - __get_user(h, ufdset+1); - ufdset += 2; - *fdset++ = h << 32 | l; - n -= 2; - } - if (odd) - __get_user(*fdset, ufdset); - } else { - /* Tricky, must clear full unsigned long in the - * kernel fdset at the end, this makes sure that - * actually happens. - */ - memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); - } - return 0; -} - -static inline void -set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) -{ - unsigned long odd; - n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); - - if (!ufdset) - return; - - odd = n & 1UL; - n &= ~1UL; - while (n) { - unsigned long h, l; - l = *fdset++; - h = l >> 32; - __put_user(l, ufdset); - __put_user(h, ufdset+1); - ufdset += 2; - n -= 2; - } - if (odd) - __put_user(*fdset, ufdset); -} - struct msgbuf32 { int mtype; char mtext[1]; -- GitLab From 20dbc9f724e02c26e30d89cf50e7ce259ab46da4 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 11:51:43 -0400 Subject: [PATCH 0596/1002] parisc: fix compile warning in mm/init.c arch/parisc/mm/init.c: In function 'free_initmem': 381: warning: passing argument 1 of 'memset' makes pointer from integer without a cast Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 6c5ea964647cf..b0831d9e35cba 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -378,7 +378,7 @@ void free_initmem(void) /* Attempt to catch anyone trying to execute code here * by filling the page with BRK insns. */ - memset(init_begin, 0x00, init_end - init_begin); + memset((void *)init_begin, 0x00, init_end - init_begin); flush_icache_range(init_begin, init_end); #endif -- GitLab From 64a0cdb026666cd9911fa045b863fb1f0f255dd8 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 13:10:03 -0400 Subject: [PATCH 0597/1002] parisc: processor.c, fix bloated stack frame The pa_pdc_cell struct can be kmalloc'd, so do that instead. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/processor.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 1ca69a808e38a..c8fb61ed32f4e 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -120,22 +120,28 @@ static int __cpuinit processor_probe(struct parisc_device *dev) if (is_pdc_pat()) { ulong status; unsigned long bytecnt; - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; + pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; #undef USE_PAT_CPUID #ifdef USE_PAT_CPUID struct pdc_pat_cpu_num cpu_info; #endif + pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL); + if (!pa_pdc_cell) + panic("couldn't allocate memory for PDC_PAT_CELL!"); + status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc, - dev->mod_index, PA_VIEW, &pa_pdc_cell); + dev->mod_index, PA_VIEW, pa_pdc_cell); BUG_ON(PDC_OK != status); /* verify it's the same as what do_pat_inventory() found */ - BUG_ON(dev->mod_info != pa_pdc_cell.mod_info); - BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location); + BUG_ON(dev->mod_info != pa_pdc_cell->mod_info); + BUG_ON(dev->pmod_loc != pa_pdc_cell->mod_location); + + txn_addr = pa_pdc_cell->mod[0]; /* id_eid for IO sapic */ - txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */ + kfree(pa_pdc_cell); #ifdef USE_PAT_CPUID /* We need contiguous numbers for cpuid. Firmware's notion -- GitLab From 0d56d1aa0e756f077b700420c54e1a52140e73b4 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 13:11:22 -0400 Subject: [PATCH 0598/1002] parisc: inventory.c, fix bloated stack frame The pa_pdc_cell struct can be kmalloc'd, so do that instead. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/kernel/inventory.c | 41 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index bd1f7f1ff74e7..d228d82378799 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -170,23 +170,27 @@ static void __init pagezero_memconfig(void) static int __init pat_query_module(ulong pcell_loc, ulong mod_index) { - pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; + pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; unsigned long bytecnt; unsigned long temp; /* 64-bit scratch value */ long status; /* PDC return value status */ struct parisc_device *dev; + pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL); + if (!pa_pdc_cell) + panic("couldn't allocate memory for PDC_PAT_CELL!"); + /* return cell module (PA or Processor view) */ status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, - PA_VIEW, &pa_pdc_cell); + PA_VIEW, pa_pdc_cell); if (status != PDC_OK) { /* no more cell modules or error */ return status; } - temp = pa_pdc_cell.cba; - dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path); + temp = pa_pdc_cell->cba; + dev = alloc_pa_dev(PAT_GET_CBA(temp), &(pa_pdc_cell->mod_path)); if (!dev) { return PDC_OK; } @@ -203,8 +207,8 @@ pat_query_module(ulong pcell_loc, ulong mod_index) /* save generic info returned from the call */ /* REVISIT: who is the consumer of this? not sure yet... */ - dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */ - dev->pmod_loc = pa_pdc_cell.mod_location; + dev->mod_info = pa_pdc_cell->mod_info; /* pass to PAT_GET_ENTITY() */ + dev->pmod_loc = pa_pdc_cell->mod_location; register_parisc_device(dev); /* advertise device */ @@ -216,14 +220,14 @@ pat_query_module(ulong pcell_loc, ulong mod_index) case PAT_ENTITY_PROC: printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n", - pa_pdc_cell.mod[0]); + pa_pdc_cell->mod[0]); break; case PAT_ENTITY_MEM: printk(KERN_DEBUG "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n", - pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], - pa_pdc_cell.mod[2]); + pa_pdc_cell->mod[0], pa_pdc_cell->mod[1], + pa_pdc_cell->mod[2]); break; case PAT_ENTITY_CA: printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc); @@ -243,23 +247,26 @@ pat_query_module(ulong pcell_loc, ulong mod_index) print_ranges: pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index, IO_VIEW, &io_pdc_cell); - printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]); - for (i = 0; i < pa_pdc_cell.mod[1]; i++) { + printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell->mod[1]); + for (i = 0; i < pa_pdc_cell->mod[1]; i++) { printk(KERN_DEBUG " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", - i, pa_pdc_cell.mod[2 + i * 3], /* type */ - pa_pdc_cell.mod[3 + i * 3], /* start */ - pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ + i, pa_pdc_cell->mod[2 + i * 3], /* type */ + pa_pdc_cell->mod[3 + i * 3], /* start */ + pa_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ printk(KERN_DEBUG " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", - i, io_pdc_cell.mod[2 + i * 3], /* type */ - io_pdc_cell.mod[3 + i * 3], /* start */ - io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */ + i, io_pdc_cell->mod[2 + i * 3], /* type */ + io_pdc_cell->mod[3 + i * 3], /* start */ + io_pdc_cell->mod[4 + i * 3]); /* finish (ie end) */ } printk(KERN_DEBUG "\n"); break; } #endif /* DEBUG_PAT */ + + kfree(pa_pdc_cell); + return PDC_OK; } -- GitLab From 538e23615fe78b6da151ef136e3f7c6ad1fda2c1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 20:22:06 -0400 Subject: [PATCH 0599/1002] parisc: wire sys_perf_counter_open to sys_ni_syscall Reserve a syscall slot for sys_perf_counter_open. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/unistd.h | 3 ++- arch/parisc/kernel/syscall_table.S | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 4e2aa0d149650..f3d3b8b012c49 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -810,8 +810,9 @@ #define __NR_preadv (__NR_Linux + 315) #define __NR_pwritev (__NR_Linux + 316) #define __NR_rt_tgsigqueueinfo (__NR_Linux + 317) +#define __NR_perf_counter_open (__NR_Linux + 318) -#define __NR_Linux_syscalls (__NR_rt_tgsigqueueinfo + 1) +#define __NR_Linux_syscalls (__NR_perf_counter_open + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 83f8959ff6504..0c83673a03aa6 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -416,6 +416,7 @@ ENTRY_COMP(preadv) /* 315 */ ENTRY_COMP(pwritev) ENTRY_COMP(rt_tgsigqueueinfo) + ENTRY_SAME(ni_syscall) /* Nothing yet */ -- GitLab From abf1e11a0dcf5514139cb76ed8eb050107653abd Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 21:32:18 -0400 Subject: [PATCH 0600/1002] parisc: add task_pt_regs macro needed for perf_counters. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/include/asm/processor.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 9d64df8754ba5..9ce66e9d1c2b8 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -18,6 +18,7 @@ #include <asm/types.h> #include <asm/system.h> #include <asm/percpu.h> + #endif /* __ASSEMBLY__ */ #define KERNEL_STACK_SIZE (4*PAGE_SIZE) @@ -127,6 +128,8 @@ struct thread_struct { unsigned long flags; }; +#define task_pt_regs(tsk) ((struct pt_regs *)&((tsk)->thread.regs)) + /* Thread struct flags. */ #define PARISC_UAC_NOPRINT (1UL << 0) /* see prctl and unaligned.c */ #define PARISC_UAC_SIGBUS (1UL << 1) -- GitLab From 2d4618dce6a318ff4ec78dfe492cc3793015d540 Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Tue, 23 Jun 2009 21:38:49 -0400 Subject: [PATCH 0601/1002] parisc: perf: wire up sys_perf_counter_open Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/Kconfig | 1 + arch/parisc/include/asm/perf_counter.h | 7 +++++++ arch/parisc/kernel/syscall_table.S | 2 +- tools/perf/perf.h | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 arch/parisc/include/asm/perf_counter.h diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 9038f39d9d736..c38bbc7af793f 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -16,6 +16,7 @@ config PARISC select RTC_DRV_GENERIC select INIT_ALL_POSSIBLE select BUG + select HAVE_PERF_COUNTERS help The PA-RISC microprocessor is designed by Hewlett-Packard and used in many of their workstations & servers (HP9000 700 and 800 series, diff --git a/arch/parisc/include/asm/perf_counter.h b/arch/parisc/include/asm/perf_counter.h new file mode 100644 index 0000000000000..dc9e829f70139 --- /dev/null +++ b/arch/parisc/include/asm/perf_counter.h @@ -0,0 +1,7 @@ +#ifndef __ASM_PARISC_PERF_COUNTER_H +#define __ASM_PARISC_PERF_COUNTER_H + +/* parisc only supports software counters through this interface. */ +static inline void set_perf_counter_pending(void) { } + +#endif /* __ASM_PARISC_PERF_COUNTER_H */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 0c83673a03aa6..cf145eb026b34 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -416,7 +416,7 @@ ENTRY_COMP(preadv) /* 315 */ ENTRY_COMP(pwritev) ENTRY_COMP(rt_tgsigqueueinfo) - ENTRY_SAME(ni_syscall) + ENTRY_SAME(perf_counter_open) /* Nothing yet */ diff --git a/tools/perf/perf.h b/tools/perf/perf.h index ceb68aa51f7f5..188801b4ebc6f 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -19,6 +19,12 @@ #define cpu_relax() asm volatile("" ::: "memory"); #endif +#ifdef __hppa__ +#include "../../arch/parisc/include/asm/unistd.h" +#define rmb() asm volatile("" ::: "memory") +#define cpu_relax() asm volatile("" ::: "memory"); +#endif + #include <time.h> #include <unistd.h> #include <sys/types.h> -- GitLab From ca0844e347cf0fc9719c825ea1959501117b7f89 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox <matthew@wil.cx> Date: Fri, 26 Jun 2009 17:44:18 +0000 Subject: [PATCH 0602/1002] parisc: Fix PCI resource allocation on non-PAT SBA machines We weren't marking the resources as memory resources, so they weren't being found by pci_claim_resource(). Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Reviewed-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/parisc/sba_iommu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index d46dd57450acd..123d8fe3427d0 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -2057,6 +2057,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) r->start = (base & ~1UL) | PCI_F_EXTEND; size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); r->end = r->start + size; + r->flags = IORESOURCE_MEM; } } @@ -2093,4 +2094,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; r->start += rope * (size + 1); /* adjust base for this rope */ r->end = r->start + size; + r->flags = IORESOURCE_MEM; } -- GitLab From 0c5cb79198d80eaea273f3e91cb418d559f13462 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov <a.beregalov@gmail.com> Date: Thu, 16 Apr 2009 14:45:59 +0000 Subject: [PATCH 0603/1002] parisc: superio: fix build breakage Usage of parport_pc_probe_port was changed in 28783eb52 (parport: Fix various uses of parport_pc). It introduced this build error: drivers/parisc/superio.c: In function 'superio_parport_init': drivers/parisc/superio.c:437: error: too few arguments to function 'parport_pc_probe_port' Fix it. Signed-off-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- drivers/parisc/superio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 589bd635e50fe..675f04e6597a5 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -434,8 +434,8 @@ static void __init superio_parport_init(void) 0 /*base_hi*/, PAR_IRQ, PARPORT_DMA_NONE /* dma */, - NULL /*struct pci_dev* */), - 0 /* shared irq flags */ ) + NULL /*struct pci_dev* */, + 0 /* shared irq flags */)) printk(KERN_WARNING PFX "Probing parallel port failed.\n"); #endif /* CONFIG_PARPORT_PC */ -- GitLab From 64daa4435a40aa1b7d0ece598ae783b89dda13ee Mon Sep 17 00:00:00 2001 From: Kyle McMartin <kyle@mcmartin.ca> Date: Thu, 2 Jul 2009 13:10:29 -0400 Subject: [PATCH 0604/1002] parisc: use generic atomic64 on 32-bit Somewhat redundant since our atomic_t uses hashed-locks on 32-bit anyway... Maybe we can clean those up to be generic too someday. Signed-off-by: Kyle McMartin <kyle@mcmartin.ca> --- arch/parisc/Kconfig | 1 + arch/parisc/include/asm/atomic.h | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index c38bbc7af793f..06f8d5b5b0f96 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -17,6 +17,7 @@ config PARISC select INIT_ALL_POSSIBLE select BUG select HAVE_PERF_COUNTERS + select GENERIC_ATOMIC64 if !64BIT help The PA-RISC microprocessor is designed by Hewlett-Packard and used in many of their workstations & servers (HP9000 700 and 800 series, diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 82e9688f658c1..8bc9e96699b2a 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -336,7 +336,11 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) -#endif /* CONFIG_64BIT */ +#else /* CONFIG_64BIT */ + +#include <asm-generic/atomic64.h> + +#endif /* !CONFIG_64BIT */ #include <asm-generic/atomic-long.h> -- GitLab From 47220f623c3216ca276bad517ed208ea2ffceaa2 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Fri, 3 Jul 2009 13:08:28 +0900 Subject: [PATCH 0605/1002] sh: define PERF_COUNTER_INDEX_OFFSET. Fixes up recent build breakage. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/include/asm/perf_counter.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sh/include/asm/perf_counter.h b/arch/sh/include/asm/perf_counter.h index 61c2b40c802cf..d8e6bb9c0ccc7 100644 --- a/arch/sh/include/asm/perf_counter.h +++ b/arch/sh/include/asm/perf_counter.h @@ -4,4 +4,6 @@ /* SH only supports software counters through this interface. */ static inline void set_perf_counter_pending(void) {} +#define PERF_COUNTER_INDEX_OFFSET 0 + #endif /* __ASM_SH_PERF_COUNTER_H */ -- GitLab From 30d7a77dd5a9720430af72f6f62f5156fe073e55 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo <acme@redhat.com> Date: Thu, 2 Jul 2009 21:24:14 -0300 Subject: [PATCH 0606/1002] perf_counter tools: Adjust symbols in ET_EXEC files too Ingo Molnar wrote: > i just bisected a 'perf report' bug that would cause us to not > resolve all user-space symbols in a 'git gc' run to: > > f5812a7a336fb952d819e4427b9a2dce02368e82 is first bad commit > commit f5812a7a336fb952d819e4427b9a2dce02368e82 > Author: Arnaldo Carvalho de Melo <acme@redhat.com> > Date: Tue Jun 30 11:43:17 2009 -0300 > > perf_counter tools: Adjust only prelinked symbol's addresses Rename ->prelinked to ->adjust_symbols and making what was done only for prelinked libraries also to ET_EXEC binaries, such as /usr/bin/git: [acme@doppio pahole]$ readelf -h /usr/bin/git | grep Type Type: EXEC (Executable file) [acme@doppio pahole]$ And after installing the 'git-debuginfo' package, I get correct results: [acme@doppio linux-2.6-tip]$ perf report --sort comm,dso,symbol -d /usr/bin/git | head -20 # # (1139614 samples) # # Overhead Command Shared Object Symbol # ........ ................ ......................... ...... # 34.98% git /usr/bin/git [.] send_sideband 33.39% git /usr/bin/git [.] enter_repo 6.81% git /usr/bin/git [.] diff_opt_parse 4.95% git /usr/bin/git [.] is_repository_shallow 3.24% git /usr/bin/git [.] odb_mkstemp 1.39% git /usr/bin/git [.] output 1.34% git /usr/bin/git [.] xmmap 1.25% git /usr/bin/git [.] receive_pack_config 1.16% git /usr/bin/git [.] git_pathdup 0.90% git /usr/bin/git [.] read_object_with_reference 0.86% git /usr/bin/git [.] show_patch_diff 0.85% git /usr/bin/git 0x00000000095e2e 0.69% git /usr/bin/git [.] display [acme@doppio linux-2.6-tip]$ I'll check what are the last cases where we can't resolve symbols, like this 0x00000000095e2e later. And I guess this will fix the problems Mike were seeing too: [acme@doppio linux-2.6-tip]$ readelf -h ../build/perf/vmlinux | grep Type Type: EXEC (Executable file) [acme@doppio linux-2.6-tip]$ Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/symbol.c | 11 ++++++----- tools/perf/util/symbol.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 98a13114de70e..4683b67b5ee43 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -555,9 +555,10 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); - self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, - ".gnu.prelink_undo", - NULL) != NULL; + self->adjust_symbols = (ehdr.e_type == ET_EXEC || + elf_section_by_name(elf, &ehdr, &shdr, + ".gnu.prelink_undo", + NULL) != NULL); elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { struct symbol *f; u64 obj_start; @@ -580,7 +581,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, section_name = elf_sec__name(&shdr, secstrs); obj_start = sym.st_value; - if (self->prelinked) { + if (self->adjust_symbols) { if (verbose >= 2) printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); @@ -632,7 +633,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) if (!name) return -1; - self->prelinked = 0; + self->adjust_symbols = 0; if (strncmp(self->name, "/tmp/perf-", 10) == 0) return dso__load_perf_map(self, filter, verbose); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 4e141a30911e6..7918cffb23cd3 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -24,7 +24,7 @@ struct dso { struct rb_root syms; struct symbol *(*find_symbol)(struct dso *, u64 ip); unsigned int sym_priv_size; - unsigned char prelinked; + unsigned char adjust_symbols; char name[0]; }; -- GitLab From 44e18e9eda1f5c318a888989d929188eea93c8dc Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@igel.co.jp> Date: Fri, 3 Jul 2009 08:39:34 +0000 Subject: [PATCH 0607/1002] sh-sci: update receive error handling for muxed irqs This patch updates the receive error code for muxed interrupts in the sh-sci driver. Receive error interrupts may be generated by the hardware if RE or REIE bits in SCSCR are set. Update the muxed interrupt handling code to acknowledge error interrupts if RE or REIE is set, instead of only acknowledging if REIE is set. Without this patch error interrupts may be generated but never acked resulting in a "nobody cared" crash. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/serial/sh-sci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 66f52674ca0cb..12bd64684f12b 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -707,12 +707,13 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) { - unsigned short ssr_status, scr_status; + unsigned short ssr_status, scr_status, err_enabled; struct uart_port *port = ptr; irqreturn_t ret = IRQ_NONE; ssr_status = sci_in(port, SCxSR); scr_status = sci_in(port, SCSCR); + err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); /* Tx Interrupt */ if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE)) @@ -721,10 +722,10 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE)) ret = sci_rx_interrupt(irq, ptr); /* Error Interrupt */ - if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE)) + if ((ssr_status & 0x0080) && err_enabled) ret = sci_er_interrupt(irq, ptr); /* Break Interrupt */ - if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE)) + if ((ssr_status & 0x0010) && err_enabled) ret = sci_br_interrupt(irq, ptr); return ret; -- GitLab From 1df892cba45f9856d369a6a317ad2d1e44bca423 Mon Sep 17 00:00:00 2001 From: Mark Brown <broonie@opensource.wolfsonmicro.com> Date: Fri, 3 Jul 2009 10:33:39 +0100 Subject: [PATCH 0608/1002] ASoC: Fix register cache initialisation for WM8753 The wrong register cache variable was being used to provide the size for the memcpy(), resulting in a copy of only a void * of data. Reported-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: stable@kernel.org --- sound/soc/codecs/wm8753.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index d28eeaceb8573..e06b0cfe4f2cc 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1664,7 +1664,7 @@ static int wm8753_register(struct wm8753_priv *wm8753) codec->reg_cache = &wm8753->reg_cache; codec->private_data = wm8753; - memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); + memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); ret = wm8753_reset(codec); -- GitLab From 07573534b0b030226ee5ab560e53aac7e6c0dd84 Mon Sep 17 00:00:00 2001 From: Grant Likely <grant.likely@secretlab.ca> Date: Thu, 2 Jul 2009 11:57:19 -0600 Subject: [PATCH 0609/1002] ASoC: Fix mpc5200-psc-ac97 to ensure the data ready bit is cleared When doing register reads, it is possible for there to be a stale data ready bit set which will cause subsequent reads to return prematurely with incorrect data. This patch fixes the issues by ensuring stale data is cleared before starting another transaction. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jon Smirl <jonsmirl@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/fsl/mpc5200_psc_ac97.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 794a247b3eb55..9b8503f2d68ce 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -41,6 +41,10 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) pr_err("timeout on ac97 bus (rdy)\n"); return -ENODEV; } + + /* Force clear the data valid bit */ + in_be32(&psc_dma->psc_regs->ac97_data); + /* Send the read */ out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24)); -- GitLab From 0827d6ba0b76be398a3c4298afd41f4965d2cdcb Mon Sep 17 00:00:00 2001 From: Grant Likely <grant.likely@secretlab.ca> Date: Thu, 2 Jul 2009 11:57:25 -0600 Subject: [PATCH 0610/1002] ASoC: add locking to mpc5200-psc-ac97 driver AC97 bus register read/write hooks need to provide locking, but the mpc5200-psc-ac97 driver does not. This patch adds a mutex around the register access routines. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Jon Smirl <jonsmirl@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/fsl/mpc5200_dma.c | 1 + sound/soc/fsl/mpc5200_dma.h | 1 + sound/soc/fsl/mpc5200_psc_ac97.c | 13 ++++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index efec33a1c5bdd..f0a2d40719981 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -456,6 +456,7 @@ int mpc5200_audio_dma_create(struct of_device *op) return -ENODEV; spin_lock_init(&psc_dma->lock); + mutex_init(&psc_dma->mutex); psc_dma->id = be32_to_cpu(*prop); psc_dma->irq = irq; psc_dma->psc_regs = regs; diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index 2000803f06a72..8d396bb9d9fe4 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -55,6 +55,7 @@ struct psc_dma { unsigned int irq; struct device *dev; spinlock_t lock; + struct mutex mutex; u32 sicr; uint sysclk; int imr; diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 9b8503f2d68ce..7eb549985d490 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -34,11 +34,14 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) int status; unsigned int val; + mutex_lock(&psc_dma->mutex); + /* Wait for command send status zero = ready */ status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & MPC52xx_PSC_SR_CMDSEND), 100, 0); if (status == 0) { pr_err("timeout on ac97 bus (rdy)\n"); + mutex_unlock(&psc_dma->mutex); return -ENODEV; } @@ -54,16 +57,19 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) if (status == 0) { pr_err("timeout on ac97 read (val) %x\n", in_be16(&psc_dma->psc_regs->sr_csr.status)); + mutex_unlock(&psc_dma->mutex); return -ENODEV; } /* Get the data */ val = in_be32(&psc_dma->psc_regs->ac97_data); if (((val >> 24) & 0x7f) != reg) { pr_err("reg echo error on ac97 read\n"); + mutex_unlock(&psc_dma->mutex); return -ENODEV; } val = (val >> 8) & 0xffff; + mutex_unlock(&psc_dma->mutex); return (unsigned short) val; } @@ -72,16 +78,21 @@ static void psc_ac97_write(struct snd_ac97 *ac97, { int status; + mutex_lock(&psc_dma->mutex); + /* Wait for command status zero = ready */ status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & MPC52xx_PSC_SR_CMDSEND), 100, 0); if (status == 0) { pr_err("timeout on ac97 bus (write)\n"); - return; + goto out; } /* Write data */ out_be32(&psc_dma->psc_regs->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8)); + + out: + mutex_unlock(&psc_dma->mutex); } static void psc_ac97_warm_reset(struct snd_ac97 *ac97) -- GitLab From 992bb253cd6f08129edcb42b90e6c388ebf605f8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Mon, 22 Jun 2009 00:00:02 +0200 Subject: [PATCH 0611/1002] mfd: sm501, fix lock imbalance Add omitted unlock in sm501_unit_power. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> --- drivers/mfd/sm501.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 4c7b7962f6b80..0cc5eeff5ee8b 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -367,7 +367,8 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to) break; default: - return -1; + gate = -1; + goto already; } writel(mode, sm->regs + SM501_POWER_MODE_CONTROL); -- GitLab From 1c90ea2c7eb3b24a07a2f82164323588fb029bc1 Mon Sep 17 00:00:00 2001 From: Daniel Ribeiro <drwyrm@gmail.com> Date: Tue, 23 Jun 2009 12:30:58 -0300 Subject: [PATCH 0612/1002] mfd: fix pcap adc locking Release the lock on error. Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> --- drivers/mfd/ezx-pcap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 671a7efe86a8b..c1de4afa89a62 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -238,8 +238,10 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap) mutex_lock(&pcap->adc_mutex); req = pcap->adc_queue[pcap->adc_head]; - if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) + if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) { + mutex_unlock(&pcap->adc_mutex); return IRQ_HANDLED; + } /* read requested channels results */ ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); -- GitLab From 029e5b1636d0511ef143af3a20c83c48e44c03f3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 13:17:28 +0200 Subject: [PATCH 0613/1002] perf report: Annotate variable initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Certain versions of GCC dont see the initialization that is done here: builtin-report.c: In function ‘__cmd_report’: builtin-report.c:1038: warning: ‘syms’ may be used uninitialized in this function So annotate it with a NULL initialization. Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 283773d91aa04..fa937f5c3c395 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1035,7 +1035,7 @@ resolve_callchain(struct thread *thread, struct map *map __used, struct ip_callchain *chain, struct hist_entry *entry) { u64 context = PERF_CONTEXT_MAX; - struct symbol **syms; + struct symbol **syms = NULL; unsigned int i; if (callchain) { -- GitLab From bbf2a330d92c5afccfd17592ba9ccd50f41cf748 Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 3 Jul 2009 00:08:26 +0200 Subject: [PATCH 0614/1002] x86: atomic64: The atomic64_t data type should be 8 bytes aligned on 32-bit too Locked instructions on two cache lines at once are painful. If atomic64_t uses two cache lines, my test program is 10x slower. The chance for that is significant: 4/32 or 12.5%. Make sure an atomic64_t is 8 bytes aligned. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> [ changed it to __aligned(8) as per Andrew's suggestion ] Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index 2503d4e64c2a7..ae0fbb5b05783 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -250,7 +250,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) /* An 64bit atomic type */ typedef struct { - unsigned long long counter; + unsigned long long __aligned(8) counter; } atomic64_t; #define ATOMIC64_INIT(val) { (val) } -- GitLab From b7882b7c65abb00194bdb3d4a22d27d70fcc59ba Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 13:26:39 +0200 Subject: [PATCH 0615/1002] x86: atomic64: Move the 32-bit atomic64_t implementation to a .c file Linus noted that the atomic64_t primitives are all inlines currently which is crazy because these functions have a large register footprint anyway. Move them to a separate file: arch/x86/lib/atomic64_32.c Also, while at it, rename all uses of 'unsigned long long' to the much shorter u64. This makes the appearance of the prototypes a lot nicer - and it also uncovered a few bugs where (yet unused) API variants had 'long' as their return type instead of u64. [ More intrusive changes are not yet done in this patch. ] Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 137 +++----------------- arch/x86/lib/Makefile | 1 + arch/x86/lib/atomic64_32.c | 216 +++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 117 deletions(-) create mode 100644 arch/x86/lib/atomic64_32.c diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index ae0fbb5b05783..311a43e47c0bb 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -250,7 +250,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) /* An 64bit atomic type */ typedef struct { - unsigned long long __aligned(8) counter; + u64 __aligned(8) counter; } atomic64_t; #define ATOMIC64_INIT(val) { (val) } @@ -264,31 +264,7 @@ typedef struct { */ #define __atomic64_read(ptr) ((ptr)->counter) -static inline unsigned long long -cmpxchg8b(unsigned long long *ptr, unsigned long long old, unsigned long long new) -{ - asm volatile( - - LOCK_PREFIX "cmpxchg8b (%[ptr])\n" - - : "=A" (old) - - : [ptr] "D" (ptr), - "A" (old), - "b" (ll_low(new)), - "c" (ll_high(new)) - - : "memory"); - - return old; -} - -static inline unsigned long long -atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val, - unsigned long long new_val) -{ - return cmpxchg8b(&ptr->counter, old_val, new_val); -} +extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); /** * atomic64_xchg - xchg atomic64 variable @@ -298,18 +274,7 @@ atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val, * Atomically xchgs the value of @ptr to @new_val and returns * the old value. */ - -static inline unsigned long long -atomic64_xchg(atomic64_t *ptr, unsigned long long new_val) -{ - unsigned long long old_val; - - do { - old_val = atomic_read(ptr); - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); - - return old_val; -} +extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); /** * atomic64_set - set atomic64 variable @@ -318,10 +283,7 @@ atomic64_xchg(atomic64_t *ptr, unsigned long long new_val) * * Atomically sets the value of @ptr to @new_val. */ -static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val) -{ - atomic64_xchg(ptr, new_val); -} +extern void atomic64_set(atomic64_t *ptr, u64 new_val); /** * atomic64_read - read atomic64 variable @@ -329,16 +291,7 @@ static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val) * * Atomically reads the value of @ptr and returns it. */ -static inline unsigned long long atomic64_read(atomic64_t *ptr) -{ - unsigned long long curr_val; - - do { - curr_val = __atomic64_read(ptr); - } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val); - - return curr_val; -} +extern u64 atomic64_read(atomic64_t *ptr); /** * atomic64_add_return - add and return @@ -347,34 +300,14 @@ static inline unsigned long long atomic64_read(atomic64_t *ptr) * * Atomically adds @delta to @ptr and returns @delta + *@ptr */ -static inline unsigned long long -atomic64_add_return(unsigned long long delta, atomic64_t *ptr) -{ - unsigned long long old_val, new_val; - - do { - old_val = atomic_read(ptr); - new_val = old_val + delta; - - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); - - return new_val; -} - -static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr) -{ - return atomic64_add_return(-delta, ptr); -} +extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); -static inline long atomic64_inc_return(atomic64_t *ptr) -{ - return atomic64_add_return(1, ptr); -} - -static inline long atomic64_dec_return(atomic64_t *ptr) -{ - return atomic64_sub_return(1, ptr); -} +/* + * Other variants with different arithmetic operators: + */ +extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); +extern u64 atomic64_inc_return(atomic64_t *ptr); +extern u64 atomic64_dec_return(atomic64_t *ptr); /** * atomic64_add - add integer to atomic64 variable @@ -383,10 +316,7 @@ static inline long atomic64_dec_return(atomic64_t *ptr) * * Atomically adds @delta to @ptr. */ -static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr) -{ - atomic64_add_return(delta, ptr); -} +extern void atomic64_add(u64 delta, atomic64_t *ptr); /** * atomic64_sub - subtract the atomic64 variable @@ -395,10 +325,7 @@ static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr) * * Atomically subtracts @delta from @ptr. */ -static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr) -{ - atomic64_add(-delta, ptr); -} +extern void atomic64_sub(u64 delta, atomic64_t *ptr); /** * atomic64_sub_and_test - subtract value from variable and test result @@ -409,13 +336,7 @@ static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr) * true if the result is zero, or false for all * other cases. */ -static inline int -atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr) -{ - unsigned long long old_val = atomic64_sub_return(delta, ptr); - - return old_val == 0; -} +extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); /** * atomic64_inc - increment atomic64 variable @@ -423,10 +344,7 @@ atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr) * * Atomically increments @ptr by 1. */ -static inline void atomic64_inc(atomic64_t *ptr) -{ - atomic64_add(1, ptr); -} +extern void atomic64_inc(atomic64_t *ptr); /** * atomic64_dec - decrement atomic64 variable @@ -434,10 +352,7 @@ static inline void atomic64_inc(atomic64_t *ptr) * * Atomically decrements @ptr by 1. */ -static inline void atomic64_dec(atomic64_t *ptr) -{ - atomic64_sub(1, ptr); -} +extern void atomic64_dec(atomic64_t *ptr); /** * atomic64_dec_and_test - decrement and test @@ -447,10 +362,7 @@ static inline void atomic64_dec(atomic64_t *ptr) * returns true if the result is 0, or false for all other * cases. */ -static inline int atomic64_dec_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(1, ptr); -} +extern int atomic64_dec_and_test(atomic64_t *ptr); /** * atomic64_inc_and_test - increment and test @@ -460,10 +372,7 @@ static inline int atomic64_dec_and_test(atomic64_t *ptr) * and returns true if the result is zero, or false for all * other cases. */ -static inline int atomic64_inc_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(-1, ptr); -} +extern int atomic64_inc_and_test(atomic64_t *ptr); /** * atomic64_add_negative - add and test if negative @@ -474,13 +383,7 @@ static inline int atomic64_inc_and_test(atomic64_t *ptr) * if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int -atomic64_add_negative(unsigned long long delta, atomic64_t *ptr) -{ - long long old_val = atomic64_add_return(delta, ptr); - - return old_val < 0; -} +extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); #include <asm-generic/atomic-long.h> #endif /* _ASM_X86_ATOMIC_32_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index f9d35632666b0..c3c657c8bb834 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,6 +10,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o ifeq ($(CONFIG_X86_32),y) + lib-y += atomic64_32.o lib-y += checksum_32.o lib-y += strstr_32.o lib-y += semaphore_32.o string_32.o diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c new file mode 100644 index 0000000000000..d21e725d3d845 --- /dev/null +++ b/arch/x86/lib/atomic64_32.c @@ -0,0 +1,216 @@ +#include <linux/compiler.h> +#include <linux/types.h> +#include <asm/processor.h> +#include <asm/cmpxchg.h> +#include <asm/atomic.h> + +static inline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) +{ + asm volatile( + + LOCK_PREFIX "cmpxchg8b (%[ptr])\n" + + : "=A" (old) + + : [ptr] "D" (ptr), + "A" (old), + "b" (ll_low(new)), + "c" (ll_high(new)) + + : "memory"); + + return old; +} + +u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val) +{ + return cmpxchg8b(&ptr->counter, old_val, new_val); +} + +/** + * atomic64_xchg - xchg atomic64 variable + * @ptr: pointer to type atomic64_t + * @new_val: value to assign + * + * Atomically xchgs the value of @ptr to @new_val and returns + * the old value. + */ + +u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) +{ + u64 old_val; + + do { + old_val = atomic_read(ptr); + } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); + + return old_val; +} + +/** + * atomic64_set - set atomic64 variable + * @ptr: pointer to type atomic64_t + * @new_val: value to assign + * + * Atomically sets the value of @ptr to @new_val. + */ +void atomic64_set(atomic64_t *ptr, u64 new_val) +{ + atomic64_xchg(ptr, new_val); +} + +/** + * atomic64_read - read atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically reads the value of @ptr and returns it. + */ +u64 atomic64_read(atomic64_t *ptr) +{ + u64 curr_val; + + do { + curr_val = __atomic64_read(ptr); + } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val); + + return curr_val; +} + +/** + * atomic64_add_return - add and return + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr and returns @delta + *@ptr + */ +u64 atomic64_add_return(u64 delta, atomic64_t *ptr) +{ + u64 old_val, new_val; + + do { + old_val = atomic_read(ptr); + new_val = old_val + delta; + + } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); + + return new_val; +} + +u64 atomic64_sub_return(u64 delta, atomic64_t *ptr) +{ + return atomic64_add_return(-delta, ptr); +} + +u64 atomic64_inc_return(atomic64_t *ptr) +{ + return atomic64_add_return(1, ptr); +} + +u64 atomic64_dec_return(atomic64_t *ptr) +{ + return atomic64_sub_return(1, ptr); +} + +/** + * atomic64_add - add integer to atomic64 variable + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr. + */ +void atomic64_add(u64 delta, atomic64_t *ptr) +{ + atomic64_add_return(delta, ptr); +} + +/** + * atomic64_sub - subtract the atomic64 variable + * @delta: integer value to subtract + * @ptr: pointer to type atomic64_t + * + * Atomically subtracts @delta from @ptr. + */ +void atomic64_sub(u64 delta, atomic64_t *ptr) +{ + atomic64_add(-delta, ptr); +} + +/** + * atomic64_sub_and_test - subtract value from variable and test result + * @delta: integer value to subtract + * @ptr: pointer to type atomic64_t + * + * Atomically subtracts @delta from @ptr and returns + * true if the result is zero, or false for all + * other cases. + */ +int atomic64_sub_and_test(u64 delta, atomic64_t *ptr) +{ + u64 old_val = atomic64_sub_return(delta, ptr); + + return old_val == 0; +} + +/** + * atomic64_inc - increment atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically increments @ptr by 1. + */ +void atomic64_inc(atomic64_t *ptr) +{ + atomic64_add(1, ptr); +} + +/** + * atomic64_dec - decrement atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically decrements @ptr by 1. + */ +void atomic64_dec(atomic64_t *ptr) +{ + atomic64_sub(1, ptr); +} + +/** + * atomic64_dec_and_test - decrement and test + * @ptr: pointer to type atomic64_t + * + * Atomically decrements @ptr by 1 and + * returns true if the result is 0, or false for all other + * cases. + */ +int atomic64_dec_and_test(atomic64_t *ptr) +{ + return atomic64_sub_and_test(1, ptr); +} + +/** + * atomic64_inc_and_test - increment and test + * @ptr: pointer to type atomic64_t + * + * Atomically increments @ptr by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +int atomic64_inc_and_test(atomic64_t *ptr) +{ + return atomic64_sub_and_test(-1, ptr); +} + +/** + * atomic64_add_negative - add and test if negative + * @delta: integer value to add + * @ptr: pointer to type atomic64_t + * + * Atomically adds @delta to @ptr and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. + */ +int atomic64_add_negative(u64 delta, atomic64_t *ptr) +{ + long long old_val = atomic64_add_return(delta, ptr); + + return old_val < 0; +} -- GitLab From aacf682fd8c66b57383c407eecd9d4a28264ee91 Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 3 Jul 2009 12:14:27 +0200 Subject: [PATCH 0616/1002] x86: atomic64: Improve atomic64_read() Linus noticed that the 32-bit version of atomic64_read() was being overly complex with re-reading the value and doing a retry loop over that. Instead we can just rely on cmpxchg8b returning either the new value or returning the current value. We can use any 'old' value, which will be faster as it can be loaded via immediates. Using some value that is not equal to the real value in memory the instruction gets faster. This also has the advantage that the CPU could avoid dirtying the cacheline. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index d21e725d3d845..afa5d444918b4 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -67,13 +67,9 @@ void atomic64_set(atomic64_t *ptr, u64 new_val) */ u64 atomic64_read(atomic64_t *ptr) { - u64 curr_val; + u64 old = 1LL << 32; - do { - curr_val = __atomic64_read(ptr); - } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val); - - return curr_val; + return cmpxchg8b(&ptr->counter, old, old); } /** -- GitLab From 69237f94e65d3d7f539f1adb98ef68685c595004 Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 3 Jul 2009 13:26:41 +0200 Subject: [PATCH 0617/1002] x86: atomic64: Improve cmpxchg8b() Rewrite cmpxchg8b() to not use %edi register but a generic "+m" constraint, to increase compiler freedom in code generation and possibly better code. Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index afa5d444918b4..5fc1e2caa5449 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -6,19 +6,14 @@ static inline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) { - asm volatile( - - LOCK_PREFIX "cmpxchg8b (%[ptr])\n" - - : "=A" (old) - - : [ptr] "D" (ptr), - "A" (old), - "b" (ll_low(new)), - "c" (ll_high(new)) - - : "memory"); + u32 low = new; + u32 high = new >> 32; + asm volatile( + LOCK_PREFIX "cmpxchg8b %1\n" + : "+A" (old), "+m" (*ptr) + : "b" (low), "c" (high) + ); return old; } -- GitLab From 824975ef190e7dcb77718d1cc2cb53769b16d918 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 12:39:07 +0200 Subject: [PATCH 0618/1002] x86: atomic64: Improve atomic64_add_return() Linus noted (based on Eric Dumazet's numbers) that we would probably be better off not trying an atomic_read() in atomic64_add_return() but intead intentionally let the first cmpxchg8b fail - to get a cache-friendly 'give me ownership of this cacheline' transaction. That can then be followed by the real cmpxchg8b which sets the value local to the CPU. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index 5fc1e2caa5449..61959627e1e13 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -76,13 +76,22 @@ u64 atomic64_read(atomic64_t *ptr) */ u64 atomic64_add_return(u64 delta, atomic64_t *ptr) { - u64 old_val, new_val; + /* + * Try first with a (probably incorrect) assumption about + * what we have there. We'll do two loops most likely, + * but we'll get an ownership MESI transaction straight away + * instead of a read transaction followed by a + * flush-for-ownership transaction: + */ + u64 old_val, new_val, real_val = 1ULL << 32; do { - old_val = atomic_read(ptr); + old_val = real_val; new_val = old_val + delta; - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); + real_val = atomic64_cmpxchg(ptr, old_val, new_val); + + } while (real_val != old_val); return new_val; } -- GitLab From 3ac805d2afd3fa4a07cb5bcf352fd7fa83f28935 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 12:51:19 +0200 Subject: [PATCH 0619/1002] x86: atomic64: Reduce size of functions cmpxchg8b is a huge instruction in terms of register footprint, we almost never want to inline it, not even within the same code module. GCC 4.3 still messes up for two functions, under-judging the true cost of this instruction - so annotate two key functions to reduce the bloat: arch/x86/lib/atomic64_32.o: text data bss dec hex filename 1763 0 0 1763 6e3 atomic64_32.o.before 435 0 0 435 1b3 atomic64_32.o.after Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index 61959627e1e13..a910238a77604 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -4,7 +4,7 @@ #include <asm/cmpxchg.h> #include <asm/atomic.h> -static inline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) +static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) { u32 low = new; u32 high = new >> 32; @@ -74,7 +74,7 @@ u64 atomic64_read(atomic64_t *ptr) * * Atomically adds @delta to @ptr and returns @delta + *@ptr */ -u64 atomic64_add_return(u64 delta, atomic64_t *ptr) +noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr) { /* * Try first with a (probably incorrect) assumption about -- GitLab From 3217120873598533234b6dedda9c371ce30001d0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 13:06:01 +0200 Subject: [PATCH 0620/1002] x86: atomic64: Make atomic_read() type-safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linus noticed that atomic64_xchg() uses atomic_read(), which happens to work because atomic_read() is a macro so the .counter value gets u64-read on 32-bit too - but this is really bogus and serious bugs are waiting to happen. Change atomic_read() to be a type-safe inline, and this exposes the atomic64 bogosity as well: arch/x86/lib/atomic64_32.c: In function ‘atomic64_xchg’: arch/x86/lib/atomic64_32.c:39: warning: passing argument 1 of ‘atomic_read’ from incompatible pointer type Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index 311a43e47c0bb..b551bb1ae3cf9 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -19,7 +19,10 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} /** * atomic_set - set atomic variable -- GitLab From 199e23780a7e75c63a9e3d1108804e3af450ea3e Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 13:02:39 +0200 Subject: [PATCH 0621/1002] x86: atomic64: Fix unclean type use in atomic64_xchg() Linus noticed that atomic64_xchg() uses atomic_read(), which happens to work because atomic_read() is a macro so the .counter value gets u64-read on 32-bit too - but this is really bogus and serious bugs are waiting to happen. Fix atomic64_xchg() to use __atomic64_read() instead. No code changed: arch/x86/lib/atomic64_32.o: text data bss dec hex filename 435 0 0 435 1b3 atomic64_32.o.before 435 0 0 435 1b3 atomic64_32.o.after md5: bd8ab95e69c93518578bfaf0ea3be4d9 atomic64_32.o.before.asm bd8ab95e69c93518578bfaf0ea3be4d9 atomic64_32.o.after.asm Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index a910238a77604..fd28fd3fb742a 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -36,7 +36,7 @@ u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) u64 old_val; do { - old_val = atomic_read(ptr); + old_val = __atomic64_read(ptr); } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); return old_val; -- GitLab From 12b9d7ccb841805e347fec8f733f368f43ddba40 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Date: Wed, 1 Jul 2009 17:37:22 -0400 Subject: [PATCH 0622/1002] x86: Fix fixmap page order for FIX_TEXT_POKE0,1 Masami reported: > Since the fixmap pages are assigned higher address to lower, > text_poke() has to use it with inverted order (FIX_TEXT_POKE1 > to FIX_TEXT_POKE0). I prefer to just invert the order of the fixmap declaration. It's simpler and more straightforward. Backward fixmaps seems to be used by both x86 32 and 64. It's really rare but a nasty bug, because it only hurts when instructions to patch are crossing a page boundary. If this happens, the fixmap write accesses will spill on the following fixmap, which may very well crash the system. And this does not crash the system, it could leave illegal instructions in place. Thanks Masami for finding this. It seems to have crept into the 2.6.30-rc series, so this calls for a -stable inclusion. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Acked-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: <stable@kernel.org> LKML-Reference: <20090701213722.GH19926@Krystal> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/fixmap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 3eb0f79a53206..7b2d71df39a6a 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -111,8 +111,8 @@ enum fixed_addresses { #ifdef CONFIG_PARAVIRT FIX_PARAVIRT_BOOTMAP, #endif - FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */ - FIX_TEXT_POKE1, + FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ + FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ __end_of_permanent_fixed_addresses, /* * 256 temporary boot-time mappings, used by early_ioremap(), -- GitLab From 3fd382cedfb4fb742a8cc17ba15288ec03131db1 Mon Sep 17 00:00:00 2001 From: Mike Galbraith <efault@gmx.de> Date: Thu, 2 Jul 2009 07:27:20 +0200 Subject: [PATCH 0623/1002] x86: Add missing annotation to arch/x86/lib/copy_user_64.S::copy_to_user While examining symbol generation in perf_counter tools, I noticed that copy_to_user() had no size in vmlinux's symtab. Signed-off-by: Mike Galbraith <efault@gmx.de> Acked-by: Alexander van Heukelum <heukelum@fastmail.fm> Acked-by: Cyrill Gorcunov <gorcunov@openvz.org> LKML-Reference: <1246512440.13293.3.camel@marge.simson.net> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/copy_user_64.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index f118c110af32f..6ba0f7bb85ead 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -75,6 +75,7 @@ ENTRY(copy_to_user) jae bad_to_user ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string CFI_ENDPROC +ENDPROC(copy_to_user) /* Standard copy_from_user with segment limit checking */ ENTRY(copy_from_user) -- GitLab From d3ac88157c1e9153f37cd2b9313117ae11735063 Mon Sep 17 00:00:00 2001 From: Rakib Mullick <rakib.mullick@gmail.com> Date: Thu, 2 Jul 2009 11:40:36 +0600 Subject: [PATCH 0624/1002] x86, kvm: Fix section mismatches in kvm.c The function paravirt_ops_setup() has been refering the variable no_timer_check, which is a __initdata. Thus generates the following warning. paravirt_ops_setup() function is called from kvm_guest_init() which is a __init function. So to fix this we mark paravirt_ops_setup as __init. The sections-check output that warned us about this was: LD arch/x86/built-in.o WARNING: arch/x86/built-in.o(.text+0x166ce): Section mismatch in reference from the function paravirt_ops_setup() to the variable .init.data:no_timer_check The function paravirt_ops_setup() references the variable __initdata no_timer_check. This is often because paravirt_ops_setup lacks a __initdata annotation or the annotation of no_timer_check is wrong. Signed-off-by: Rakib Mullick <rakib.mullick@gmail.com> Acked-by: Avi Kivity <avi@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <b9df5fa10907012240y356427b8ta4bd07f0efc6a049@mail.gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index a78ecad0c900f..c664d515f6135 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -200,7 +200,7 @@ static void kvm_leave_lazy_mmu(void) state->mode = paravirt_get_lazy_mode(); } -static void paravirt_ops_setup(void) +static void __init paravirt_ops_setup(void) { pv_info.name = "KVM"; pv_info.paravirt_enabled = 1; -- GitLab From 23d0cd8e718723f1ddda37637bc6b7c34caec64a Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 2 Jul 2009 22:33:59 +0530 Subject: [PATCH 0625/1002] x86: Remove unused variable disable_x2apic setup_nox2apic() is writing 1 to disable_x2apic but no one is reading it. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Cyrill Gorcunov <gorcunov@gmail.com> LKML-Reference: <1246554239.2242.27.camel@jaswinder.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/kernel/apic/apic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 8c7c042ecad1e..0a1c2830ec662 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -140,7 +140,6 @@ int x2apic_mode; #ifdef CONFIG_X86_X2APIC /* x2apic enabled before OS handover */ static int x2apic_preenabled; -static int disable_x2apic; static __init int setup_nox2apic(char *str) { if (x2apic_enabled()) { @@ -149,7 +148,6 @@ static __init int setup_nox2apic(char *str) return 0; } - disable_x2apic = 1; setup_clear_cpu_cap(X86_FEATURE_X2APIC); return 0; } -- GitLab From c7210e1ff8a95a0a6dba0d04a95b3ddd9d165fab Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Thu, 2 Jul 2009 22:35:35 +0530 Subject: [PATCH 0626/1002] x86: Remove unused function lapic_watchdog_ok() lapic_watchdog_ok() is a global function but no one is using it. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Yinghai Lu <yinghai@kernel.org> LKML-Reference: <1246554335.2242.29.camel@jaswinder.satnam> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/nmi.h | 1 - arch/x86/kernel/cpu/perfctr-watchdog.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index c97264409934b..c86e5ed4af51d 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h @@ -72,7 +72,6 @@ void lapic_watchdog_stop(void); int lapic_watchdog_init(unsigned nmi_hz); int lapic_wd_event(unsigned nmi_hz); unsigned lapic_adjust_nmi_hz(unsigned hz); -int lapic_watchdog_ok(void); void disable_lapic_nmi_watchdog(void); void enable_lapic_nmi_watchdog(void); void stop_nmi(void); diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 5c481f6205bfc..e60ed740d2b3f 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c @@ -803,8 +803,3 @@ int __kprobes lapic_wd_event(unsigned nmi_hz) wd_ops->rearm(wd, nmi_hz); return 1; } - -int lapic_watchdog_ok(void) -{ - return wd_ops != NULL; -} -- GitLab From 8e049ef054f1cc765f05f13e1396bb9a17c19e66 Mon Sep 17 00:00:00 2001 From: Paul Mackerras <paulus@samba.org> Date: Thu, 2 Jul 2009 08:57:12 +1000 Subject: [PATCH 0627/1002] x86: atomic64: Code atomic(64)_read and atomic(64)_set in C not CPP Occasionally we get bugs where atomic_read or atomic_set are used on atomic64_t variables or vice versa. These bugs don't generate warnings on x86 because atomic_read and atomic_set are coded as macros rather than C functions, so we don't get any type-checking on their arguments; similarly for atomic64_read and atomic64_set in 64-bit kernels. This converts them to C functions so that the arguments are type-checked and bugs like this will get caught more easily. It also converts atomic_cmpxchg and atomic_xchg, and atomic64_cmpxchg and atomic64_xchg on 64-bit, so we get type-checking on their arguments too. Compiling a typical 64-bit x86 config, this generates no new warnings, and the vmlinux text is 86 bytes smaller. Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 16 +++++++++--- arch/x86/include/asm/atomic_64.h | 42 ++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index b551bb1ae3cf9..aa045deb2e757 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -31,7 +31,10 @@ static inline int atomic_read(const atomic_t *v) * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) (((v)->counter) = (i)) +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} /** * atomic_add - add integer to atomic variable @@ -203,8 +206,15 @@ static inline int atomic_sub_return(int i, atomic_t *v) return atomic_add_return(-i, v); } -#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline int atomic_xchg(atomic_t *v, int new) +{ + return xchg(&v->counter, new); +} /** * atomic_add_unless - add unless the number is already a given value diff --git a/arch/x86/include/asm/atomic_64.h b/arch/x86/include/asm/atomic_64.h index 0d6360220007b..d605dc268e798 100644 --- a/arch/x86/include/asm/atomic_64.h +++ b/arch/x86/include/asm/atomic_64.h @@ -18,7 +18,10 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} /** * atomic_set - set atomic variable @@ -27,7 +30,10 @@ * * Atomically sets the value of @v to @i. */ -#define atomic_set(v, i) (((v)->counter) = (i)) +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} /** * atomic_add - add integer to atomic variable @@ -192,7 +198,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) * Atomically reads the value of @v. * Doesn't imply a read memory barrier. */ -#define atomic64_read(v) ((v)->counter) +static inline long atomic64_read(const atomic64_t *v) +{ + return v->counter; +} /** * atomic64_set - set atomic64 variable @@ -201,7 +210,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) * * Atomically sets the value of @v to @i. */ -#define atomic64_set(v, i) (((v)->counter) = (i)) +static inline void atomic64_set(atomic64_t *v, long i) +{ + v->counter = i; +} /** * atomic64_add - add integer to atomic64 variable @@ -355,11 +367,25 @@ static inline long atomic64_sub_return(long i, atomic64_t *v) #define atomic64_inc_return(v) (atomic64_add_return(1, (v))) #define atomic64_dec_return(v) (atomic64_sub_return(1, (v))) -#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) +static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline long atomic64_xchg(atomic64_t *v, long new) +{ + return xchg(&v->counter, new); +} -#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) -#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) +static inline long atomic_cmpxchg(atomic_t *v, int old, int new) +{ + return cmpxchg(&v->counter, old, new); +} + +static inline long atomic_xchg(atomic_t *v, int new) +{ + return xchg(&v->counter, new); +} /** * atomic_add_unless - add unless the number is a given value -- GitLab From 67d7178f8fc64b7f68d7dd8a1b21dfa0d42c220c Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 3 Jul 2009 13:23:02 +0200 Subject: [PATCH 0628/1002] x86: atomic64: Improve atomic64_read() Optimize atomic64_read() as a special open-coded cmpxchg8b variant. This generates nicer code: arch/x86/lib/atomic64_32.o: text data bss dec hex filename 435 0 0 435 1b3 atomic64_32.o.before 431 0 0 431 1af atomic64_32.o.after md5: bd8ab95e69c93518578bfaf0ea3be4d9 atomic64_32.o.before.asm 2bdfd4bd1f6b7b61b7fc127aef90ce3b atomic64_32.o.after.asm Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907021653030.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index fd28fd3fb742a..cd11803f9448f 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -62,9 +62,17 @@ void atomic64_set(atomic64_t *ptr, u64 new_val) */ u64 atomic64_read(atomic64_t *ptr) { - u64 old = 1LL << 32; + u64 res; - return cmpxchg8b(&ptr->counter, old, old); + asm volatile( + "mov %%ebx, %%eax\n\t" + "mov %%ecx, %%edx\n\t" + LOCK_PREFIX "cmpxchg8b %1\n" + : "+A" (res) + : "m" (*ptr) + ); + + return res; } /** -- GitLab From 099db17e66294b02814dee01c81d9abbbeece93e Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Thu, 2 Jul 2009 16:10:23 +0200 Subject: [PATCH 0629/1002] ALSA: hda - Add GPIO1 control at muting with HP laptops HP laptops with AD1984A codecs (at least mobile models) need to set GPIO1 appropriately to indicate the mute state. The BIOS checks this bit to judge whether the mute on or off is sent via F8 key. Without changing this bit, the BIOS can be confused and may toggle the mute wrongly. Reference: Novell bnc#515266 https://bugzilla.novell.com/show_bug.cgi?id=515266 Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_analog.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 85e8618e8497d..f795ee588cc78 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3734,9 +3734,30 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { { } /* end */ }; +static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + int mute = (!ucontrol->value.integer.value[0] && + !ucontrol->value.integer.value[1]); + /* toggle GPIO1 according to the mute state */ + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, + mute ? 0x02 : 0x0); + return ret; +} + static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), + /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .info = snd_hda_mixer_amp_switch_info, + .get = snd_hda_mixer_amp_switch_get, + .put = ad1884a_mobile_master_sw_put, + .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), + }, HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), @@ -3857,6 +3878,10 @@ static struct hda_verb ad1884a_mobile_verbs[] = { /* unsolicited event for pin-sense */ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, + /* allow to touch GPIO1 (for mute control) */ + {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ { } /* end */ }; -- GitLab From aa202455eec51699e44f658530728162cefa1307 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Fri, 3 Jul 2009 15:00:54 +0200 Subject: [PATCH 0630/1002] ALSA: hda - Improve ASUS eeePC 1000 mixer The mixer elements created for ASUS eeePC 1000 with ALC269 aren't standard but strange words like "LineOut". Rename the element names to follow the standard one like "Headphone" and "Speaker". Also, split the volumes to each so that the virtual master can control them. The alc269_fujitsu_mixer is removed because it's now identical with the new eeepc mixer. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3a8e58c483dfd..e661b21354bed 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12876,20 +12876,11 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { { } }; -/* bind volumes of both NID 0x0c and 0x0d */ -static struct hda_bind_ctls alc269_epc_bind_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT), - 0 - }, -}; - static struct snd_kcontrol_new alc269_eeepc_mixer[] = { - HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol), - HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -12902,12 +12893,7 @@ static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { }; /* FSC amilo */ -static struct snd_kcontrol_new alc269_fujitsu_mixer[] = { - HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol), - { } /* end */ -}; +#define alc269_fujitsu_mixer alc269_eeepc_mixer static struct hda_verb alc269_quanta_fl1_verbs[] = { {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, -- GitLab From 637a935aaba2f05e2178c9d1b714d7a2c36c8b44 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen <lars@metafoo.de> Date: Fri, 3 Jul 2009 01:04:16 +0200 Subject: [PATCH 0631/1002] ASoC: Fix wm8753 register cache size and initialization Register cache space was not being allocated for the final register, causing bugs when it was used. Allocate space for it. Also ensure that the final register is displayed in sysfs. [Commit message rewritten to document actual issue. -- broonie] Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> --- sound/soc/codecs/wm8753.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index e06b0cfe4f2cc..49c4b2898aff5 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = { 0x0097, 0x0097, 0x0000, 0x0004, 0x0000, 0x0083, 0x0024, 0x01ba, 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0000 + 0x0000, 0x0000, 0x0000 }; /* codec private data */ @@ -1660,7 +1660,7 @@ static int wm8753_register(struct wm8753_priv *wm8753) codec->set_bias_level = wm8753_set_bias_level; codec->dai = wm8753_dai; codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); + codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; codec->reg_cache = &wm8753->reg_cache; codec->private_data = wm8753; -- GitLab From 033a666ccb842ab4134fcd0c861d5ba9f5d6bf3a Mon Sep 17 00:00:00 2001 From: David Howells <dhowells@redhat.com> Date: Thu, 2 Jul 2009 14:35:32 +0100 Subject: [PATCH 0632/1002] NFSD: Don't hold unrefcounted creds over call to nfsd_setuser() nfsd_open() gets an unrefcounted pointer to the current process's effective credentials at the top of the function, then calls nfsd_setuser() via fh_verify() - which may replace and destroy the current process's effective credentials - and then passes the unrefcounted pointer to dentry_open() - but the credentials may have been destroyed by this point. Instead, the value from current_cred() should be passed directly to dentry_open() as one of its arguments, rather than being cached in a variable. Possibly fh_verify() should return the creds to use. This is a regression introduced by 745ca2475a6ac596e3d8d37c2759c0fbe2586227 "CRED: Pass credentials through dentry_open()". Signed-off-by: David Howells <dhowells@redhat.com> Tested-and-Verified-By: Steve Dickson <steved@redhat.com> Cc: stable@kernel.org Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> --- fs/nfsd/vfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4145083dcf881..23341c1063bcd 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -678,7 +678,6 @@ __be32 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access, struct file **filp) { - const struct cred *cred = current_cred(); struct dentry *dentry; struct inode *inode; int flags = O_RDONLY|O_LARGEFILE; @@ -733,7 +732,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, vfs_dq_init(inode); } *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), - flags, cred); + flags, current_cred()); if (IS_ERR(*filp)) host_err = PTR_ERR(*filp); else -- GitLab From 7ca5dc145bc7daddd8aed8bbda46b74af9cebefc Mon Sep 17 00:00:00 2001 From: Florian Fainelli <florian@openwrt.org> Date: Wed, 24 Jun 2009 11:12:57 +0200 Subject: [PATCH 0633/1002] MIPS: Add support for Texas Instruments AR7 System-on-a-Chip This patch adds support for the Texas Instruments AR7 System-on-a-Chip. It supports the TNETD7100, 7200 and 7300 versions of the SoC. Signed-off-by: Matteo Croce <matteo@openwrt.org> Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Eugene Konev <ejka@openwrt.org> Signed-off-by: Nicolas Thill <nico@openwrt.org> Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/Kconfig | 20 + arch/mips/Makefile | 7 + arch/mips/ar7/Makefile | 10 + arch/mips/ar7/clock.c | 440 +++++++++ arch/mips/ar7/gpio.c | 48 + arch/mips/ar7/irq.c | 176 ++++ arch/mips/ar7/memory.c | 72 ++ arch/mips/ar7/platform.c | 555 +++++++++++ arch/mips/ar7/prom.c | 297 ++++++ arch/mips/ar7/setup.c | 94 ++ arch/mips/ar7/time.c | 30 + arch/mips/configs/ar7_defconfig | 1182 +++++++++++++++++++++++ arch/mips/include/asm/mach-ar7/ar7.h | 178 ++++ arch/mips/include/asm/mach-ar7/gpio.h | 110 +++ arch/mips/include/asm/mach-ar7/irq.h | 16 + arch/mips/include/asm/mach-ar7/prom.h | 25 + arch/mips/include/asm/mach-ar7/spaces.h | 22 + arch/mips/include/asm/mach-ar7/war.h | 25 + 18 files changed, 3307 insertions(+) create mode 100644 arch/mips/ar7/Makefile create mode 100644 arch/mips/ar7/clock.c create mode 100644 arch/mips/ar7/gpio.c create mode 100644 arch/mips/ar7/irq.c create mode 100644 arch/mips/ar7/memory.c create mode 100644 arch/mips/ar7/platform.c create mode 100644 arch/mips/ar7/prom.c create mode 100644 arch/mips/ar7/setup.c create mode 100644 arch/mips/ar7/time.c create mode 100644 arch/mips/configs/ar7_defconfig create mode 100644 arch/mips/include/asm/mach-ar7/ar7.h create mode 100644 arch/mips/include/asm/mach-ar7/gpio.h create mode 100644 arch/mips/include/asm/mach-ar7/irq.h create mode 100644 arch/mips/include/asm/mach-ar7/prom.h create mode 100644 arch/mips/include/asm/mach-ar7/spaces.h create mode 100644 arch/mips/include/asm/mach-ar7/war.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8c4be1f301cf2..b0e55113633ad 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -22,6 +22,26 @@ choice config MACH_ALCHEMY bool "Alchemy processor based machines" +config AR7 + bool "Texas Instruments AR7" + select BOOT_ELF32 + select DMA_NONCOHERENT + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select NO_EXCEPT_FILL + select SWAP_IO_SPACE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_GPIO + select GCD + select VLYNQ + help + Support for the Texas Instruments AR7 System-on-a-Chip + family: TNETD7100, 7200 and 7300. + config BASLER_EXCITE bool "Basler eXcite smart camera" select CEVT_R4K diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 807572a6a4d2d..861da514a468a 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -172,6 +172,13 @@ libs-y += arch/mips/fw/lib/ # Board-dependent options and extra files # +# +# Texas Instruments AR7 +# +core-$(CONFIG_AR7) += arch/mips/ar7/ +cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 +load-$(CONFIG_AR7) += 0xffffffff94100000 + # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile new file mode 100644 index 0000000000000..7435e44b39640 --- /dev/null +++ b/arch/mips/ar7/Makefile @@ -0,0 +1,10 @@ + +obj-y := \ + prom.o \ + setup.o \ + memory.o \ + irq.o \ + time.o \ + platform.o \ + gpio.o \ + clock.o diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c new file mode 100644 index 0000000000000..27dc6663f2fa5 --- /dev/null +++ b/arch/mips/ar7/clock.c @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/gcd.h> +#include <linux/io.h> + +#include <asm/addrspace.h> +#include <asm/mach-ar7/ar7.h> + +#define BOOT_PLL_SOURCE_MASK 0x3 +#define CPU_PLL_SOURCE_SHIFT 16 +#define BUS_PLL_SOURCE_SHIFT 14 +#define USB_PLL_SOURCE_SHIFT 18 +#define DSP_PLL_SOURCE_SHIFT 22 +#define BOOT_PLL_SOURCE_AFE 0 +#define BOOT_PLL_SOURCE_BUS 0 +#define BOOT_PLL_SOURCE_REF 1 +#define BOOT_PLL_SOURCE_XTAL 2 +#define BOOT_PLL_SOURCE_CPU 3 +#define BOOT_PLL_BYPASS 0x00000020 +#define BOOT_PLL_ASYNC_MODE 0x02000000 +#define BOOT_PLL_2TO1_MODE 0x00008000 + +#define TNETD7200_CLOCK_ID_CPU 0 +#define TNETD7200_CLOCK_ID_DSP 1 +#define TNETD7200_CLOCK_ID_USB 2 + +#define TNETD7200_DEF_CPU_CLK 211000000 +#define TNETD7200_DEF_DSP_CLK 125000000 +#define TNETD7200_DEF_USB_CLK 48000000 + +struct tnetd7300_clock { + u32 ctrl; +#define PREDIV_MASK 0x001f0000 +#define PREDIV_SHIFT 16 +#define POSTDIV_MASK 0x0000001f + u32 unused1[3]; + u32 pll; +#define MUL_MASK 0x0000f000 +#define MUL_SHIFT 12 +#define PLL_MODE_MASK 0x00000001 +#define PLL_NDIV 0x00000800 +#define PLL_DIV 0x00000002 +#define PLL_STATUS 0x00000001 + u32 unused2[3]; +}; + +struct tnetd7300_clocks { + struct tnetd7300_clock bus; + struct tnetd7300_clock cpu; + struct tnetd7300_clock usb; + struct tnetd7300_clock dsp; +}; + +struct tnetd7200_clock { + u32 ctrl; + u32 unused1[3]; +#define DIVISOR_ENABLE_MASK 0x00008000 + u32 mul; + u32 prediv; + u32 postdiv; + u32 postdiv2; + u32 unused2[6]; + u32 cmd; + u32 status; + u32 cmden; + u32 padding[15]; +}; + +struct tnetd7200_clocks { + struct tnetd7200_clock cpu; + struct tnetd7200_clock dsp; + struct tnetd7200_clock usb; +}; + +int ar7_cpu_clock = 150000000; +EXPORT_SYMBOL(ar7_cpu_clock); +int ar7_bus_clock = 125000000; +EXPORT_SYMBOL(ar7_bus_clock); +int ar7_dsp_clock; +EXPORT_SYMBOL(ar7_dsp_clock); + +static void approximate(int base, int target, int *prediv, + int *postdiv, int *mul) +{ + int i, j, k, freq, res = target; + for (i = 1; i <= 16; i++) + for (j = 1; j <= 32; j++) + for (k = 1; k <= 32; k++) { + freq = abs(base / j * i / k - target); + if (freq < res) { + res = freq; + *mul = i; + *prediv = j; + *postdiv = k; + } + } +} + +static void calculate(int base, int target, int *prediv, int *postdiv, + int *mul) +{ + int tmp_gcd, tmp_base, tmp_freq; + + for (*prediv = 1; *prediv <= 32; (*prediv)++) { + tmp_base = base / *prediv; + tmp_gcd = gcd(target, tmp_base); + *mul = target / tmp_gcd; + *postdiv = tmp_base / tmp_gcd; + if ((*mul < 1) || (*mul >= 16)) + continue; + if ((*postdiv > 0) & (*postdiv <= 32)) + break; + } + + if (base / *prediv * *mul / *postdiv != target) { + approximate(base, target, prediv, postdiv, mul); + tmp_freq = base / *prediv * *mul / *postdiv; + printk(KERN_WARNING + "Adjusted requested frequency %d to %d\n", + target, tmp_freq); + } + + printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n", + *prediv, *postdiv, *mul); +} + +static int tnetd7300_dsp_clock(void) +{ + u32 didr1, didr2; + u8 rev = ar7_chip_rev(); + didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18)); + didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c)); + if (didr2 & (1 << 23)) + return 0; + if ((rev >= 0x23) && (rev != 0x57)) + return 250000000; + if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22)) + > 4208000) + return 250000000; + return 0; +} + +static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock, + u32 *bootcr, u32 bus_clock) +{ + int product; + int base_clock = AR7_REF_CLOCK; + u32 ctrl = readl(&clock->ctrl); + u32 pll = readl(&clock->pll); + int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1; + int postdiv = (ctrl & POSTDIV_MASK) + 1; + int divisor = prediv * postdiv; + int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1; + + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { + case BOOT_PLL_SOURCE_BUS: + base_clock = bus_clock; + break; + case BOOT_PLL_SOURCE_REF: + base_clock = AR7_REF_CLOCK; + break; + case BOOT_PLL_SOURCE_XTAL: + base_clock = AR7_XTAL_CLOCK; + break; + case BOOT_PLL_SOURCE_CPU: + base_clock = ar7_cpu_clock; + break; + } + + if (*bootcr & BOOT_PLL_BYPASS) + return base_clock / divisor; + + if ((pll & PLL_MODE_MASK) == 0) + return (base_clock >> (mul / 16 + 1)) / divisor; + + if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) { + product = (mul & 1) ? + (base_clock * mul) >> 1 : + (base_clock * (mul - 1)) >> 2; + return product / divisor; + } + + if (mul == 16) + return base_clock / divisor; + + return base_clock * mul / divisor; +} + +static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, + u32 *bootcr, u32 frequency) +{ + int prediv, postdiv, mul; + int base_clock = ar7_bus_clock; + + switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { + case BOOT_PLL_SOURCE_BUS: + base_clock = ar7_bus_clock; + break; + case BOOT_PLL_SOURCE_REF: + base_clock = AR7_REF_CLOCK; + break; + case BOOT_PLL_SOURCE_XTAL: + base_clock = AR7_XTAL_CLOCK; + break; + case BOOT_PLL_SOURCE_CPU: + base_clock = ar7_cpu_clock; + break; + } + + calculate(base_clock, frequency, &prediv, &postdiv, &mul); + + writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); + msleep(1); + writel(4, &clock->pll); + while (readl(&clock->pll) & PLL_STATUS) + ; + writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); + msleep(75); +} + +static void __init tnetd7300_init_clocks(void) +{ + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + struct tnetd7300_clocks *clocks = + ioremap_nocache(UR8_REGS_CLOCKS, + sizeof(struct tnetd7300_clocks)); + + ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, + &clocks->bus, bootcr, AR7_AFE_CLOCK); + + if (*bootcr & BOOT_PLL_ASYNC_MODE) + ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT, + &clocks->cpu, bootcr, AR7_AFE_CLOCK); + else + ar7_cpu_clock = ar7_bus_clock; + + if (ar7_dsp_clock == 250000000) + tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, + bootcr, ar7_dsp_clock); + + iounmap(clocks); + iounmap(bootcr); +} + +static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock, + u32 *bootcr, u32 bus_clock) +{ + int divisor = ((readl(&clock->prediv) & 0x1f) + 1) * + ((readl(&clock->postdiv) & 0x1f) + 1); + + if (*bootcr & BOOT_PLL_BYPASS) + return base / divisor; + + return base * ((readl(&clock->mul) & 0xf) + 1) / divisor; +} + + +static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock, + int prediv, int postdiv, int postdiv2, int mul, u32 frequency) +{ + printk(KERN_INFO + "Clocks: base = %d, frequency = %u, prediv = %d, " + "postdiv = %d, postdiv2 = %d, mul = %d\n", + base, frequency, prediv, postdiv, postdiv2, mul); + + writel(0, &clock->ctrl); + writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv); + writel((mul - 1) & 0xF, &clock->mul); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv); + + writel(readl(&clock->cmden) | 1, &clock->cmden); + writel(readl(&clock->cmd) | 1, &clock->cmd); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2); + + writel(readl(&clock->cmden) | 1, &clock->cmden); + writel(readl(&clock->cmd) | 1, &clock->cmd); + + while (readl(&clock->status) & 0x1) + ; /* nop */ + + writel(readl(&clock->ctrl) | 1, &clock->ctrl); +} + +static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr) +{ + if (*bootcr & BOOT_PLL_ASYNC_MODE) + /* Async */ + switch (clock_id) { + case TNETD7200_CLOCK_ID_DSP: + return AR7_REF_CLOCK; + default: + return AR7_AFE_CLOCK; + } + else + /* Sync */ + if (*bootcr & BOOT_PLL_2TO1_MODE) + /* 2:1 */ + switch (clock_id) { + case TNETD7200_CLOCK_ID_DSP: + return AR7_REF_CLOCK; + default: + return AR7_AFE_CLOCK; + } + else + /* 1:1 */ + return AR7_REF_CLOCK; +} + + +static void __init tnetd7200_init_clocks(void) +{ + u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + struct tnetd7200_clocks *clocks = + ioremap_nocache(AR7_REGS_CLOCKS, + sizeof(struct tnetd7200_clocks)); + int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv; + int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv; + int usb_base, usb_mul, usb_prediv, usb_postdiv; + + cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr); + dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr); + + if (*bootcr & BOOT_PLL_ASYNC_MODE) { + printk(KERN_INFO "Clocks: Async mode\n"); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, + &dsp_prediv, &dsp_postdiv, &dsp_mul); + ar7_bus_clock = + ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2, + ar7_bus_clock); + + printk(KERN_INFO "Clocks: Setting CPU clock\n"); + calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, + &cpu_postdiv, &cpu_mul); + ar7_cpu_clock = + ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv; + tnetd7200_set_clock(cpu_base, &clocks->cpu, + cpu_prediv, cpu_postdiv, -1, cpu_mul, + ar7_cpu_clock); + + } else + if (*bootcr & BOOT_PLL_2TO1_MODE) { + printk(KERN_INFO "Clocks: Sync 2:1 mode\n"); + + printk(KERN_INFO "Clocks: Setting CPU clock\n"); + calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, + &cpu_postdiv, &cpu_mul); + ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul) + / cpu_postdiv; + tnetd7200_set_clock(cpu_base, &clocks->cpu, + cpu_prediv, cpu_postdiv, -1, cpu_mul, + ar7_cpu_clock); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, + &dsp_postdiv, &dsp_mul); + ar7_bus_clock = ar7_cpu_clock / 2; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, + dsp_mul * 2, ar7_bus_clock); + } else { + printk(KERN_INFO "Clocks: Sync 1:1 mode\n"); + + printk(KERN_INFO "Clocks: Setting DSP clock\n"); + calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, + &dsp_postdiv, &dsp_mul); + ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul) + / dsp_postdiv; + tnetd7200_set_clock(dsp_base, &clocks->dsp, + dsp_prediv, dsp_postdiv * 2, dsp_postdiv, + dsp_mul * 2, ar7_bus_clock); + + ar7_cpu_clock = ar7_bus_clock; + } + + printk(KERN_INFO "Clocks: Setting USB clock\n"); + usb_base = ar7_bus_clock; + calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv, + &usb_postdiv, &usb_mul); + tnetd7200_set_clock(usb_base, &clocks->usb, + usb_prediv, usb_postdiv, -1, usb_mul, + TNETD7200_DEF_USB_CLK); + + ar7_dsp_clock = ar7_cpu_clock; + + iounmap(clocks); + iounmap(bootcr); +} + +int __init ar7_init_clocks(void) +{ + switch (ar7_chip_id()) { + case AR7_CHIP_7100: + case AR7_CHIP_7200: + tnetd7200_init_clocks(); + break; + case AR7_CHIP_7300: + ar7_dsp_clock = tnetd7300_dsp_clock(); + tnetd7300_init_clocks(); + break; + default: + break; + } + + return 0; +} +arch_initcall(ar7_init_clocks); diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c new file mode 100644 index 0000000000000..74e14a3dbf4aa --- /dev/null +++ b/arch/mips/ar7/gpio.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/module.h> + +#include <asm/mach-ar7/gpio.h> + +static const char *ar7_gpio_list[AR7_GPIO_MAX]; + +int gpio_request(unsigned gpio, const char *label) +{ + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + if (ar7_gpio_list[gpio]) + return -EBUSY; + + if (label) + ar7_gpio_list[gpio] = label; + else + ar7_gpio_list[gpio] = "busy"; + + return 0; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned gpio) +{ + BUG_ON(!ar7_gpio_list[gpio]); + ar7_gpio_list[gpio] = NULL; +} +EXPORT_SYMBOL(gpio_free); diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c new file mode 100644 index 0000000000000..c781556c44e46 --- /dev/null +++ b/arch/mips/ar7/irq.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/interrupt.h> +#include <linux/io.h> + +#include <asm/irq_cpu.h> +#include <asm/mipsregs.h> +#include <asm/mach-ar7/ar7.h> + +#define EXCEPT_OFFSET 0x80 +#define PACE_OFFSET 0xA0 +#define CHNLS_OFFSET 0x200 + +#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10) +#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8) +#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */ +#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */ +#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */ +#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */ +#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */ +#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */ +#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */ +#define PIR_OFFSET (0x40) +#define MSR_OFFSET (0x44) +#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */ +#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */ + +#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr)) + +#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4)) + +static int ar7_irq_base; + +static void ar7_unmask_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ESR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_mask_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(ECR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_ack_irq(unsigned int irq) +{ + writel(1 << ((irq - ar7_irq_base) % 32), + REG(CR_OFFSET(irq - ar7_irq_base))); +} + +static void ar7_unmask_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); +} + +static void ar7_mask_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); +} + +static void ar7_ack_sec_irq(unsigned int irq) +{ + writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); +} + +static struct irq_chip ar7_irq_type = { + .name = "AR7", + .unmask = ar7_unmask_irq, + .mask = ar7_mask_irq, + .ack = ar7_ack_irq +}; + +static struct irq_chip ar7_sec_irq_type = { + .name = "AR7", + .unmask = ar7_unmask_sec_irq, + .mask = ar7_mask_sec_irq, + .ack = ar7_ack_sec_irq, +}; + +static struct irqaction ar7_cascade_action = { + .handler = no_action, + .name = "AR7 cascade interrupt" +}; + +static void __init ar7_irq_init(int base) +{ + int i; + /* + * Disable interrupts and clear pending + */ + writel(0xffffffff, REG(ECR_OFFSET(0))); + writel(0xff, REG(ECR_OFFSET(32))); + writel(0xffffffff, REG(SEC_ECR_OFFSET)); + writel(0xffffffff, REG(CR_OFFSET(0))); + writel(0xff, REG(CR_OFFSET(32))); + writel(0xffffffff, REG(SEC_CR_OFFSET)); + + ar7_irq_base = base; + + for (i = 0; i < 40; i++) { + writel(i, REG(CHNL_OFFSET(i))); + /* Primary IRQ's */ + set_irq_chip_and_handler(base + i, &ar7_irq_type, + handle_level_irq); + /* Secondary IRQ's */ + if (i < 32) + set_irq_chip_and_handler(base + i + 40, + &ar7_sec_irq_type, + handle_level_irq); + } + + setup_irq(2, &ar7_cascade_action); + setup_irq(ar7_irq_base, &ar7_cascade_action); + set_c0_status(IE_IRQ0); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + ar7_irq_init(8); +} + +static void ar7_cascade(void) +{ + u32 status; + int i, irq; + + /* Primary IRQ's */ + irq = readl(REG(PIR_OFFSET)) & 0x3f; + if (irq) { + do_IRQ(ar7_irq_base + irq); + return; + } + + /* Secondary IRQ's are cascaded through primary '0' */ + writel(1, REG(CR_OFFSET(irq))); + status = readl(REG(SEC_SR_OFFSET)); + for (i = 0; i < 32; i++) { + if (status & 1) { + do_IRQ(ar7_irq_base + i + 40); + return; + } + status >>= 1; + } + + spurious_interrupt(); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + if (pending & STATUSF_IP7) /* cpu timer */ + do_IRQ(7); + else if (pending & STATUSF_IP2) /* int0 hardware line */ + ar7_cascade(); + else + spurious_interrupt(); +} diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c new file mode 100644 index 0000000000000..46fed44825a6e --- /dev/null +++ b/arch/mips/ar7/memory.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/bootmem.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/pfn.h> +#include <linux/proc_fs.h> +#include <linux/string.h> +#include <linux/swap.h> + +#include <asm/bootinfo.h> +#include <asm/page.h> +#include <asm/sections.h> + +#include <asm/mach-ar7/ar7.h> +#include <asm/mips-boards/prom.h> + +static int __init memsize(void) +{ + u32 size = (64 << 20); + u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4); + u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end)); + u32 *tmpaddr = addr; + + while (tmpaddr > kernel_end) { + *tmpaddr = (u32)tmpaddr; + size >>= 1; + tmpaddr -= size >> 2; + } + + do { + tmpaddr += size >> 2; + if (*tmpaddr != (u32)tmpaddr) + break; + size <<= 1; + } while (size < (64 << 20)); + + writel(tmpaddr, &addr); + + return size; +} + +void __init prom_meminit(void) +{ + unsigned long pages; + + pages = memsize() >> PAGE_SHIFT; + add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT, + BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ + /* Nothing to free */ +} diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c new file mode 100644 index 0000000000000..542244961780d --- /dev/null +++ b/arch/mips/ar7/platform.c @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> +#include <linux/serial.h> +#include <linux/serial_8250.h> +#include <linux/ioport.h> +#include <linux/io.h> +#include <linux/version.h> +#include <linux/vlynq.h> +#include <linux/leds.h> +#include <linux/string.h> +#include <linux/etherdevice.h> + +#include <asm/addrspace.h> +#include <asm/mach-ar7/ar7.h> +#include <asm/mach-ar7/gpio.h> +#include <asm/mach-ar7/prom.h> + +struct plat_vlynq_data { + struct plat_vlynq_ops ops; + int gpio_bit; + int reset_bit; +}; + + +static int vlynq_on(struct vlynq_device *dev) +{ + int result; + struct plat_vlynq_data *pdata = dev->dev.platform_data; + + result = gpio_request(pdata->gpio_bit, "vlynq"); + if (result) + goto out; + + ar7_device_reset(pdata->reset_bit); + + result = ar7_gpio_disable(pdata->gpio_bit); + if (result) + goto out_enabled; + + result = ar7_gpio_enable(pdata->gpio_bit); + if (result) + goto out_enabled; + + result = gpio_direction_output(pdata->gpio_bit, 0); + if (result) + goto out_gpio_enabled; + + msleep(50); + + gpio_set_value(pdata->gpio_bit, 1); + msleep(50); + + return 0; + +out_gpio_enabled: + ar7_gpio_disable(pdata->gpio_bit); +out_enabled: + ar7_device_disable(pdata->reset_bit); + gpio_free(pdata->gpio_bit); +out: + return result; +} + +static void vlynq_off(struct vlynq_device *dev) +{ + struct plat_vlynq_data *pdata = dev->dev.platform_data; + ar7_gpio_disable(pdata->gpio_bit); + gpio_free(pdata->gpio_bit); + ar7_device_disable(pdata->reset_bit); +} + +static struct resource physmap_flash_resource = { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x10000000, + .end = 0x107fffff, +}; + +static struct resource cpmac_low_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_MAC0, + .end = AR7_REGS_MAC0 + 0x7ff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 27, + .end = 27, + }, +}; + +static struct resource cpmac_high_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_MAC1, + .end = AR7_REGS_MAC1 + 0x7ff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 41, + .end = 41, + }, +}; + +static struct resource vlynq_low_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_VLYNQ0, + .end = AR7_REGS_VLYNQ0 + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 29, + .end = 29, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x04000000, + .end = 0x04ffffff, + }, + { + .name = "devirq", + .flags = IORESOURCE_IRQ, + .start = 80, + .end = 111, + }, +}; + +static struct resource vlynq_high_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_VLYNQ1, + .end = AR7_REGS_VLYNQ1 + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 33, + .end = 33, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x0c000000, + .end = 0x0cffffff, + }, + { + .name = "devirq", + .flags = IORESOURCE_IRQ, + .start = 112, + .end = 143, + }, +}; + +static struct resource usb_res[] = { + { + .name = "regs", + .flags = IORESOURCE_MEM, + .start = AR7_REGS_USB, + .end = AR7_REGS_USB + 0xff, + }, + { + .name = "irq", + .flags = IORESOURCE_IRQ, + .start = 32, + .end = 32, + }, + { + .name = "mem", + .flags = IORESOURCE_MEM, + .start = 0x03400000, + .end = 0x034001fff, + }, +}; + +static struct physmap_flash_data physmap_flash_data = { + .width = 2, +}; + +static struct plat_cpmac_data cpmac_low_data = { + .reset_bit = 17, + .power_bit = 20, + .phy_mask = 0x80000000, +}; + +static struct plat_cpmac_data cpmac_high_data = { + .reset_bit = 21, + .power_bit = 22, + .phy_mask = 0x7fffffff, +}; + +static struct plat_vlynq_data vlynq_low_data = { + .ops.on = vlynq_on, + .ops.off = vlynq_off, + .reset_bit = 20, + .gpio_bit = 18, +}; + +static struct plat_vlynq_data vlynq_high_data = { + .ops.on = vlynq_on, + .ops.off = vlynq_off, + .reset_bit = 16, + .gpio_bit = 19, +}; + +static struct platform_device physmap_flash = { + .id = 0, + .name = "physmap-flash", + .dev.platform_data = &physmap_flash_data, + .resource = &physmap_flash_resource, + .num_resources = 1, +}; + +static u64 cpmac_dma_mask = DMA_32BIT_MASK; +static struct platform_device cpmac_low = { + .id = 0, + .name = "cpmac", + .dev = { + .dma_mask = &cpmac_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = &cpmac_low_data, + }, + .resource = cpmac_low_res, + .num_resources = ARRAY_SIZE(cpmac_low_res), +}; + +static struct platform_device cpmac_high = { + .id = 1, + .name = "cpmac", + .dev = { + .dma_mask = &cpmac_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = &cpmac_high_data, + }, + .resource = cpmac_high_res, + .num_resources = ARRAY_SIZE(cpmac_high_res), +}; + +static struct platform_device vlynq_low = { + .id = 0, + .name = "vlynq", + .dev.platform_data = &vlynq_low_data, + .resource = vlynq_low_res, + .num_resources = ARRAY_SIZE(vlynq_low_res), +}; + +static struct platform_device vlynq_high = { + .id = 1, + .name = "vlynq", + .dev.platform_data = &vlynq_high_data, + .resource = vlynq_high_res, + .num_resources = ARRAY_SIZE(vlynq_high_res), +}; + + +static struct gpio_led default_leds[] = { + { + .name = "status", + .gpio = 8, + .active_low = 1, + }, +}; + +static struct gpio_led dsl502t_leds[] = { + { + .name = "status", + .gpio = 9, + .active_low = 1, + }, + { + .name = "ethernet", + .gpio = 7, + .active_low = 1, + }, + { + .name = "usb", + .gpio = 12, + .active_low = 1, + }, +}; + +static struct gpio_led dg834g_leds[] = { + { + .name = "ppp", + .gpio = 6, + .active_low = 1, + }, + { + .name = "status", + .gpio = 7, + .active_low = 1, + }, + { + .name = "adsl", + .gpio = 8, + .active_low = 1, + }, + { + .name = "wifi", + .gpio = 12, + .active_low = 1, + }, + { + .name = "power", + .gpio = 14, + .active_low = 1, + .default_trigger = "default-on", + }, +}; + +static struct gpio_led fb_sl_leds[] = { + { + .name = "1", + .gpio = 7, + }, + { + .name = "2", + .gpio = 13, + .active_low = 1, + }, + { + .name = "3", + .gpio = 10, + .active_low = 1, + }, + { + .name = "4", + .gpio = 12, + .active_low = 1, + }, + { + .name = "5", + .gpio = 9, + .active_low = 1, + }, +}; + +static struct gpio_led fb_fon_leds[] = { + { + .name = "1", + .gpio = 8, + }, + { + .name = "2", + .gpio = 3, + .active_low = 1, + }, + { + .name = "3", + .gpio = 5, + }, + { + .name = "4", + .gpio = 4, + .active_low = 1, + }, + { + .name = "5", + .gpio = 11, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data ar7_led_data; + +static struct platform_device ar7_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &ar7_led_data, + } +}; + +static struct platform_device ar7_udc = { + .id = -1, + .name = "ar7_udc", + .resource = usb_res, + .num_resources = ARRAY_SIZE(usb_res), +}; + +static inline unsigned char char2hex(char h) +{ + switch (h) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return h - '0'; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return h - 'A' + 10; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return h - 'a' + 10; + default: + return 0; + } +} + +static void cpmac_get_mac(int instance, unsigned char *dev_addr) +{ + int i; + char name[5], default_mac[ETH_ALEN], *mac; + + mac = NULL; + sprintf(name, "mac%c", 'a' + instance); + mac = prom_getenv(name); + if (!mac) { + sprintf(name, "mac%c", 'a'); + mac = prom_getenv(name); + } + if (!mac) { + random_ether_addr(default_mac); + mac = default_mac; + } + for (i = 0; i < 6; i++) + dev_addr[i] = (char2hex(mac[i * 3]) << 4) + + char2hex(mac[i * 3 + 1]); +} + +static void __init detect_leds(void) +{ + char *prid, *usb_prod; + + /* Default LEDs */ + ar7_led_data.num_leds = ARRAY_SIZE(default_leds); + ar7_led_data.leds = default_leds; + + /* FIXME: the whole thing is unreliable */ + prid = prom_getenv("ProductID"); + usb_prod = prom_getenv("usb_prod"); + + /* If we can't get the product id from PROM, use the default LEDs */ + if (!prid) + return; + + if (strstr(prid, "Fritz_Box_FON")) { + ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds); + ar7_led_data.leds = fb_fon_leds; + } else if (strstr(prid, "Fritz_Box_")) { + ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds); + ar7_led_data.leds = fb_sl_leds; + } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB")) + && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) { + ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds); + ar7_led_data.leds = dsl502t_leds; + } else if (strstr(prid, "DG834")) { + ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); + ar7_led_data.leds = dg834g_leds; + } +} + +static int __init ar7_register_devices(void) +{ + int res; + static struct uart_port uart_port[2]; + + memset(uart_port, 0, sizeof(struct uart_port) * 2); + + uart_port[0].type = PORT_16550A; + uart_port[0].line = 0; + uart_port[0].irq = AR7_IRQ_UART0; + uart_port[0].uartclk = ar7_bus_freq() / 2; + uart_port[0].iotype = UPIO_MEM32; + uart_port[0].mapbase = AR7_REGS_UART0; + uart_port[0].membase = ioremap(uart_port[0].mapbase, 256); + uart_port[0].regshift = 2; + res = early_serial_setup(&uart_port[0]); + if (res) + return res; + + + /* Only TNETD73xx have a second serial port */ + if (ar7_has_second_uart()) { + uart_port[1].type = PORT_16550A; + uart_port[1].line = 1; + uart_port[1].irq = AR7_IRQ_UART1; + uart_port[1].uartclk = ar7_bus_freq() / 2; + uart_port[1].iotype = UPIO_MEM32; + uart_port[1].mapbase = UR8_REGS_UART1; + uart_port[1].membase = ioremap(uart_port[1].mapbase, 256); + uart_port[1].regshift = 2; + res = early_serial_setup(&uart_port[1]); + if (res) + return res; + } + + res = platform_device_register(&physmap_flash); + if (res) + return res; + + ar7_device_disable(vlynq_low_data.reset_bit); + res = platform_device_register(&vlynq_low); + if (res) + return res; + + if (ar7_has_high_vlynq()) { + ar7_device_disable(vlynq_high_data.reset_bit); + res = platform_device_register(&vlynq_high); + if (res) + return res; + } + + if (ar7_has_high_cpmac()) { + cpmac_get_mac(1, cpmac_high_data.dev_addr); + res = platform_device_register(&cpmac_high); + if (res) + return res; + } else { + cpmac_low_data.phy_mask = 0xffffffff; + } + + cpmac_get_mac(0, cpmac_low_data.dev_addr); + res = platform_device_register(&cpmac_low); + if (res) + return res; + + detect_leds(); + res = platform_device_register(&ar7_gpio_leds); + if (res) + return res; + + res = platform_device_register(&ar7_udc); + + return res; +} +arch_initcall(ar7_register_devices); diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c new file mode 100644 index 0000000000000..a320bceb2f9db --- /dev/null +++ b/arch/mips/ar7/prom.c @@ -0,0 +1,297 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Putting things on the screen/serial line using YAMONs facilities. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/serial_reg.h> +#include <linux/spinlock.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/io.h> +#include <asm/bootinfo.h> + +#include <asm/mach-ar7/ar7.h> +#include <asm/mach-ar7/prom.h> + +#define MAX_ENTRY 80 + +struct env_var { + char *name; + char *value; +}; + +static struct env_var adam2_env[MAX_ENTRY]; + +char *prom_getenv(const char *name) +{ + int i; + for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++) + if (!strcmp(name, adam2_env[i].name)) + return adam2_env[i].value; + + return NULL; +} +EXPORT_SYMBOL(prom_getenv); + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +static void __init ar7_init_cmdline(int argc, char *argv[]) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while (actr < argc) { + strcpy(cp, argv[actr]); + cp += strlen(argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) { + /* get rid of trailing space */ + --cp; + *cp = '\0'; + } +} + +struct psbl_rec { + u32 psbl_size; + u32 env_base; + u32 env_size; + u32 ffs_base; + u32 ffs_size; +}; + +static __initdata char psp_env_version[] = "TIENV0.8"; + +struct psp_env_chunk { + u8 num; + u8 ctrl; + u16 csum; + u8 len; + char data[11]; +} __attribute__ ((packed)); + +struct psp_var_map_entry { + u8 num; + char *value; +}; + +static struct psp_var_map_entry psp_var_map[] = { + { 1, "cpufrequency" }, + { 2, "memsize" }, + { 3, "flashsize" }, + { 4, "modetty0" }, + { 5, "modetty1" }, + { 8, "maca" }, + { 9, "macb" }, + { 28, "sysfrequency" }, + { 38, "mipsfrequency" }, +}; + +/* + +Well-known variable (num is looked up in table above for matching variable name) +Example: cpufrequency=211968000 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Name=Value pair in a single chunk +Example: NAME=VALUE ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Name=Value pair in 2 chunks (len is the number of chunks) +Example: bootloaderVersion=1.3.7.15 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- +| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0 ++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- + +Data is padded with 0xFF + +*/ + +#define PSP_ENV_SIZE 4096 + +static char psp_env_data[PSP_ENV_SIZE] = { 0, }; + +static char * __init lookup_psp_var_map(u8 num) +{ + int i; + + for (i = 0; i < sizeof(psp_var_map); i++) + if (psp_var_map[i].num == num) + return psp_var_map[i].value; + + return NULL; +} + +static void __init add_adam2_var(char *name, char *value) +{ + int i; + for (i = 0; i < MAX_ENTRY; i++) { + if (!adam2_env[i].name) { + adam2_env[i].name = name; + adam2_env[i].value = value; + return; + } else if (!strcmp(adam2_env[i].name, name)) { + adam2_env[i].value = value; + return; + } + } +} + +static int __init parse_psp_env(void *psp_env_base) +{ + int i, n; + char *name, *value; + struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data; + + memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE); + + i = 1; + n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk); + while (i < n) { + if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n)) + break; + value = chunks[i].data; + if (chunks[i].num) { + name = lookup_psp_var_map(chunks[i].num); + } else { + name = value; + value += strlen(name) + 1; + } + if (name) + add_adam2_var(name, value); + i += chunks[i].len; + } + return 0; +} + +static void __init ar7_init_env(struct env_var *env) +{ + int i; + struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300)); + void *psp_env = (void *)KSEG1ADDR(psbl->env_base); + + if (strcmp(psp_env, psp_env_version) == 0) { + parse_psp_env(psp_env); + } else { + for (i = 0; i < MAX_ENTRY; i++, env++) + if (env->name) + add_adam2_var(env->name, env->value); + } +} + +static void __init console_config(void) +{ +#ifdef CONFIG_SERIAL_8250_CONSOLE + char console_string[40]; + int baud = 0; + char parity = '\0', bits = '\0', flow = '\0'; + char *s, *p; + + if (strstr(prom_getcmdline(), "console=")) + return; + +#ifdef CONFIG_KGDB + if (!strstr(prom_getcmdline(), "nokgdb")) { + strcat(prom_getcmdline(), " console=kgdb"); + kgdb_enabled = 1; + return; + } +#endif + + s = prom_getenv("modetty0"); + if (s) { + baud = simple_strtoul(s, &p, 10); + s = p; + if (*s == ',') + s++; + if (*s) + parity = *s++; + if (*s == ',') + s++; + if (*s) + bits = *s++; + if (*s == ',') + s++; + if (*s == 'h') + flow = 'r'; + } + + if (baud == 0) + baud = 38400; + if (parity != 'n' && parity != 'o' && parity != 'e') + parity = 'n'; + if (bits != '7' && bits != '8') + bits = '8'; + + if (flow == 'r') + sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, + parity, bits, flow); + else + sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity, + bits); + strcat(prom_getcmdline(), console_string); +#endif +} + +void __init prom_init(void) +{ + ar7_init_cmdline(fw_arg0, (char **)fw_arg1); + ar7_init_env((struct env_var *)fw_arg2); + console_config(); +} + +#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4))) +static inline unsigned int serial_in(int offset) +{ + return readl((void *)PORT(offset)); +} + +static inline void serial_out(int offset, int value) +{ + writel(value, (void *)PORT(offset)); +} + +char prom_getchar(void) +{ + while (!(serial_in(UART_LSR) & UART_LSR_DR)) + ; + return serial_in(UART_RX); +} + +int prom_putchar(char c) +{ + while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0) + ; + serial_out(UART_TX, c); + return 1; +} + diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c new file mode 100644 index 0000000000000..6ebb5f16d9675 --- /dev/null +++ b/arch/mips/ar7/setup.c @@ -0,0 +1,94 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include <linux/version.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/pm.h> +#include <linux/time.h> + +#include <asm/reboot.h> +#include <asm/mach-ar7/ar7.h> +#include <asm/mach-ar7/prom.h> + +static void ar7_machine_restart(char *command) +{ + u32 *softres_reg = ioremap(AR7_REGS_RESET + + AR7_RESET_SOFTWARE, 1); + writel(1, softres_reg); +} + +static void ar7_machine_halt(void) +{ + while (1) + ; +} + +static void ar7_machine_power_off(void) +{ + u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1); + u32 power_state = readl(power_reg) | (3 << 30); + writel(power_state, power_reg); + ar7_machine_halt(); +} + +const char *get_system_type(void) +{ + u16 chip_id = ar7_chip_id(); + switch (chip_id) { + case AR7_CHIP_7300: + return "TI AR7 (TNETD7300)"; + case AR7_CHIP_7100: + return "TI AR7 (TNETD7100)"; + case AR7_CHIP_7200: + return "TI AR7 (TNETD7200)"; + default: + return "TI AR7 (Unknown)"; + } +} + +static int __init ar7_init_console(void) +{ + return 0; +} +console_initcall(ar7_init_console); + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ + +void __init plat_mem_setup(void) +{ + unsigned long io_base; + + _machine_restart = ar7_machine_restart; + _machine_halt = ar7_machine_halt; + pm_power_off = ar7_machine_power_off; + panic_timeout = 3; + + io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); + if (!io_base) + panic("Can't remap IO base!\n"); + set_io_port_base(io_base); + + prom_meminit(); + + printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n", + get_system_type(), + ar7_chip_id(), ar7_chip_rev()); +} diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c new file mode 100644 index 0000000000000..a1fba894daa25 --- /dev/null +++ b/arch/mips/ar7/time.c @@ -0,0 +1,30 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Setting up the clock on the MIPS boards. + */ + +#include <linux/init.h> +#include <linux/time.h> + +#include <asm/time.h> +#include <asm/mach-ar7/ar7.h> + +void __init plat_time_init(void) +{ + mips_hpt_frequency = ar7_cpu_freq() / 2; +} diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig new file mode 100644 index 0000000000000..dad5b6769d746 --- /dev/null +++ b/arch/mips/configs/ar7_defconfig @@ -0,0 +1,1182 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.30 +# Wed Jun 24 14:08:59 2009 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set +CONFIG_AR7=y +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_NEC_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_NO_EXCEPT_FILL=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_HARDWARE_WATCHPOINTS=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_32KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_KEXEC=y +# CONFIG_SECCOMP is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +# CONFIG_PCSPKR_PLATFORM is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_SLOW_WORK is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_PROBE_INITRD_HEADER=y +# CONFIG_FREEZER is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_CUBIC is not set +CONFIG_TCP_CONG_WESTWOOD=y +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_DEFAULT_BIC is not set +# CONFIG_DEFAULT_CUBIC is not set +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +CONFIG_DEFAULT_WESTWOOD=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="westwood" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NF_CONNTRACK=m +# CONFIG_NF_CT_ACCT is not set +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +CONFIG_NF_CONNTRACK_FTP=m +# CONFIG_NF_CONNTRACK_H323 is not set +CONFIG_NF_CONNTRACK_IRC=m +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=m +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_STATE=m +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_NF_NAT_SNMP_BASIC is not set +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_H323 is not set +# CONFIG_NF_NAT_SIP is not set +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +CONFIG_ATM=m +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_STP=y +CONFIG_BRIDGE=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_ATM is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_INGRESS is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_EMATCH is not set +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +# CONFIG_AX25 is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_DEFAULT_PS=y +CONFIG_MAC80211_DEFAULT_PS_VALUE=1 + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set +CONFIG_MAC80211_RC_DEFAULT="pid" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_IFB is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +CONFIG_CPMAC=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_LIBERTAS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_P54_COMMON is not set +# CONFIG_HOSTAP is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_RT2X00 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_TCP is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AR7_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=y +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_SERIAL=y +CONFIG_SSB_DRIVER_MIPS=y +CONFIG_SSB_EMBEDDED=y +CONFIG_SSB_DRIVER_EXTIF=y + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_GPIO is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +CONFIG_VLYNQ=y +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=m +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h new file mode 100644 index 0000000000000..de71694614de8 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __AR7_H__ +#define __AR7_H__ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/errno.h> + +#include <asm/addrspace.h> + +#define AR7_SDRAM_BASE 0x14000000 + +#define AR7_REGS_BASE 0x08610000 + +#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000) +#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900) +/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */ +#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00) +#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80) +#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20) +#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00) +#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200) +#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600) +#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800) +#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00) +#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00) +#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00) +#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400) +#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800) + +#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00) +#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) +#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) + +#define AR7_RESET_PEREPHERIAL 0x0 +#define AR7_RESET_SOFTWARE 0x4 +#define AR7_RESET_STATUS 0x8 + +#define AR7_RESET_BIT_CPMAC_LO 17 +#define AR7_RESET_BIT_CPMAC_HI 21 +#define AR7_RESET_BIT_MDIO 22 +#define AR7_RESET_BIT_EPHY 26 + +/* GPIO control registers */ +#define AR7_GPIO_INPUT 0x0 +#define AR7_GPIO_OUTPUT 0x4 +#define AR7_GPIO_DIR 0x8 +#define AR7_GPIO_ENABLE 0xc + +#define AR7_CHIP_7100 0x18 +#define AR7_CHIP_7200 0x2b +#define AR7_CHIP_7300 0x05 + +/* Interrupts */ +#define AR7_IRQ_UART0 15 +#define AR7_IRQ_UART1 16 + +/* Clocks */ +#define AR7_AFE_CLOCK 35328000 +#define AR7_REF_CLOCK 25000000 +#define AR7_XTAL_CLOCK 24000000 + +struct plat_cpmac_data { + int reset_bit; + int power_bit; + u32 phy_mask; + char dev_addr[6]; +}; + +struct plat_dsl_data { + int reset_bit_dsl; + int reset_bit_sar; +}; + +extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock; + +static inline u16 ar7_chip_id(void) +{ + return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff; +} + +static inline u8 ar7_chip_rev(void) +{ + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff; +} + +static inline int ar7_cpu_freq(void) +{ + return ar7_cpu_clock; +} + +static inline int ar7_bus_freq(void) +{ + return ar7_bus_clock; +} + +static inline int ar7_vbus_freq(void) +{ + return ar7_bus_clock / 2; +} +#define ar7_cpmac_freq ar7_vbus_freq + +static inline int ar7_dsp_freq(void) +{ + return ar7_dsp_clock; +} + +static inline int ar7_has_high_cpmac(void) +{ + u16 chip_id = ar7_chip_id(); + switch (chip_id) { + case AR7_CHIP_7100: + case AR7_CHIP_7200: + return 0; + case AR7_CHIP_7300: + return 1; + default: + return -ENXIO; + } +} +#define ar7_has_high_vlynq ar7_has_high_cpmac +#define ar7_has_second_uart ar7_has_high_cpmac + +static inline void ar7_device_enable(u32 bit) +{ + void *reset_reg = + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); + writel(readl(reset_reg) | (1 << bit), reset_reg); + msleep(20); +} + +static inline void ar7_device_disable(u32 bit) +{ + void *reset_reg = + (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); + writel(readl(reset_reg) & ~(1 << bit), reset_reg); + msleep(20); +} + +static inline void ar7_device_reset(u32 bit) +{ + ar7_device_disable(bit); + ar7_device_enable(bit); +} + +static inline void ar7_device_on(u32 bit) +{ + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); + writel(readl(power_reg) | (1 << bit), power_reg); + msleep(20); +} + +static inline void ar7_device_off(u32 bit) +{ + void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); + writel(readl(power_reg) & ~(1 << bit), power_reg); + msleep(20); +} + +#endif /* __AR7_H__ */ diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h new file mode 100644 index 0000000000000..cbe9c4f126df6 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/gpio.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __AR7_GPIO_H__ +#define __AR7_GPIO_H__ + +#include <asm/mach-ar7/ar7.h> + +#define AR7_GPIO_MAX 32 + +extern int gpio_request(unsigned gpio, const char *label); +extern void gpio_free(unsigned gpio); + +/* Common GPIO layer */ +static inline int gpio_get_value(unsigned gpio) +{ + void __iomem *gpio_in = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT); + + return readl(gpio_in) & (1 << gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + void __iomem *gpio_out = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT); + unsigned tmp; + + tmp = readl(gpio_out) & ~(1 << gpio); + if (value) + tmp |= 1 << gpio; + writel(tmp, gpio_out); +} + +static inline int gpio_direction_input(unsigned gpio) +{ + void __iomem *gpio_dir = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); + + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + writel(readl(gpio_dir) | (1 << gpio), gpio_dir); + + return 0; +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + void __iomem *gpio_dir = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); + + if (gpio >= AR7_GPIO_MAX) + return -EINVAL; + + gpio_set_value(gpio, value); + writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir); + + return 0; +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return -EINVAL; +} + +/* Board specific GPIO functions */ +static inline int ar7_gpio_enable(unsigned gpio) +{ + void __iomem *gpio_en = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); + + writel(readl(gpio_en) | (1 << gpio), gpio_en); + + return 0; +} + +static inline int ar7_gpio_disable(unsigned gpio) +{ + void __iomem *gpio_en = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); + + writel(readl(gpio_en) & ~(1 << gpio), gpio_en); + + return 0; +} + +#include <asm-generic/gpio.h> + +#endif diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h new file mode 100644 index 0000000000000..39e9757e3d938 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/irq.h @@ -0,0 +1,16 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Shamelessly copied from asm-mips/mach-emma2rh/ + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_AR7_IRQ_H +#define __ASM_AR7_IRQ_H + +#define NR_IRQS 256 + +#include_next <irq.h> + +#endif /* __ASM_AR7_IRQ_H */ diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h new file mode 100644 index 0000000000000..088f61fe85ea6 --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/prom.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2006, 2007 Florian Fainelli <florian@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __PROM_H__ +#define __PROM_H__ + +extern char *prom_getenv(const char *name); +extern void prom_meminit(void); + +#endif /* __PROM_H__ */ diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h new file mode 100644 index 0000000000000..ac28f273449cf --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/spaces.h @@ -0,0 +1,22 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_AR7_SPACES_H +#define _ASM_AR7_SPACES_H + +/* + * This handles the memory map. + * We handle pages at KSEG0 for kernels with 32 bit address space. + */ +#define PAGE_OFFSET 0x94000000UL +#define PHYS_OFFSET 0x14000000UL + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_AR7_SPACES_H */ diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h new file mode 100644 index 0000000000000..f4862b563080c --- /dev/null +++ b/arch/mips/include/asm/mach-ar7/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> + */ +#ifndef __ASM_MIPS_MACH_AR7_WAR_H +#define __ASM_MIPS_MACH_AR7_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_AR7_WAR_H */ -- GitLab From 52a7a27cd8f6c57817da99fef019e37b9c303c4e Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 09:26:09 -0700 Subject: [PATCH 0634/1002] MIPS: MT: Remove unnecessary semicolons Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/kernel/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3ca5f42e819dc..07b9ec2c6e3d0 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -1387,7 +1387,7 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, return len; out_einval: - return -EINVAL;; + return -EINVAL; } static struct device_attribute vpe_class_attributes[] = { -- GitLab From d7e014db374d987c6bcff0b9abab2c6796f8e793 Mon Sep 17 00:00:00 2001 From: Dmitri Vorobiev <dmitri.vorobiev@movial.com> Date: Fri, 26 Jun 2009 19:59:25 +0300 Subject: [PATCH 0635/1002] MIPS: Malta: Remove unnecessary function prototypes Signed-off-by: Dmitri Vorobiev <dmitri.vorobiev@movial.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/mti-malta/malta-reset.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index 42dee4da37bad..f48d60e842901 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -28,9 +28,6 @@ #include <asm/reboot.h> #include <asm/mips-boards/generic.h> -static void mips_machine_restart(char *command); -static void mips_machine_halt(void); - static void mips_machine_restart(char *command) { unsigned int __iomem *softres_reg = -- GitLab From 69f16c9a8630edc64cb1d6f1bfca4ee7bc16279f Mon Sep 17 00:00:00 2001 From: David Daney <ddaney@caviumnetworks.com> Date: Fri, 26 Jun 2009 09:53:57 -0700 Subject: [PATCH 0636/1002] MIPS: Hookup new syscalls sys_rt_tgsigqueueinfo and sys_perf_counter_open. [Ralf: I fixed up the numbering in the comment in scall64-n32.S.] Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/unistd.h | 18 ++++++++++++------ arch/mips/kernel/scall32-o32.S | 2 ++ arch/mips/kernel/scall64-64.S | 2 ++ arch/mips/kernel/scall64-n32.S | 2 ++ arch/mips/kernel/scall64-o32.S | 2 ++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 40005010827cb..b70c49fdda26a 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -352,16 +352,18 @@ #define __NR_inotify_init1 (__NR_Linux + 329) #define __NR_preadv (__NR_Linux + 330) #define __NR_pwritev (__NR_Linux + 331) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332) +#define __NR_perf_counter_open (__NR_Linux + 333) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 331 +#define __NR_Linux_syscalls 333 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 331 +#define __NR_O32_Linux_syscalls 333 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -660,16 +662,18 @@ #define __NR_inotify_init1 (__NR_Linux + 288) #define __NR_preadv (__NR_Linux + 289) #define __NR_pwritev (__NR_Linux + 290) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291) +#define __NR_perf_counter_open (__NR_Linux + 292) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 290 +#define __NR_Linux_syscalls 292 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 290 +#define __NR_64_Linux_syscalls 292 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -972,16 +976,18 @@ #define __NR_inotify_init1 (__NR_Linux + 292) #define __NR_preadv (__NR_Linux + 293) #define __NR_pwritev (__NR_Linux + 294) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295) +#define __NR_perf_counter_open (__NR_Linux + 296) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 294 +#define __NR_Linux_syscalls 296 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 294 +#define __NR_N32_Linux_syscalls 296 #ifdef __KERNEL__ diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 0b31b9bda0486..20a86e08fd58d 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -652,6 +652,8 @@ einval: li v0, -ENOSYS sys sys_inotify_init1 1 sys sys_preadv 6 /* 4330 */ sys sys_pwritev 6 + sys sys_rt_tgsigqueueinfo 4 + sys sys_perf_counter_open 5 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index c647fd6e722f7..b046130d4c5d5 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -489,4 +489,6 @@ sys_call_table: PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev /* 5390 */ + PTR sys_rt_tgsigqueueinfo + PTR sys_perf_counter_open .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 93cc672f45221..15874f9812ccc 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -415,4 +415,6 @@ EXPORT(sysn32_call_table) PTR sys_inotify_init1 PTR sys_preadv PTR sys_pwritev + PTR compat_sys_rt_tgsigqueueinfo /* 5295 */ + PTR sys_perf_counter_open .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index a5598b2339dd4..781e0f1e9533a 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -535,4 +535,6 @@ sys_call_table: PTR sys_inotify_init1 PTR compat_sys_preadv /* 4330 */ PTR compat_sys_pwritev + PTR compat_sys_rt_tgsigqueueinfo + PTR sys_perf_counter_open .size sys_call_table,.-sys_call_table -- GitLab From 27fdd325dace4a1ebfa10e93ba6f3d25f25df674 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa <yyuasa@linux.com> Date: Mon, 29 Jun 2009 11:11:05 +0900 Subject: [PATCH 0637/1002] MIPS: Update VR41xx GPIO driver to use gpiolib Signed-off-by: Yoichi Yuasa <yyuasa@linux.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/Kconfig | 1 + arch/mips/include/asm/vr41xx/giu.h | 22 +- drivers/char/Kconfig | 4 - drivers/char/Makefile | 1 - drivers/char/vr41xx_giu.c | 680 ----------------------------- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/vr41xx_giu.c | 586 +++++++++++++++++++++++++ 8 files changed, 597 insertions(+), 704 deletions(-) create mode 100644 drivers/gpio/vr41xx_giu.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b0e55113633ad..64891f74019fa 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -267,6 +267,7 @@ config MACH_VR41XX select CEVT_R4K select CSRC_R4K select SYS_HAS_CPU_VR41XX + select ARCH_REQUIRE_GPIOLIB config NXP_STB220 bool "NXP STB220 board" diff --git a/arch/mips/include/asm/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h index 0bcdd3a5c2560..b369c091b0edd 100644 --- a/arch/mips/include/asm/vr41xx/giu.h +++ b/arch/mips/include/asm/vr41xx/giu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series General-purpose I/O Unit. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,7 +41,8 @@ typedef enum { IRQ_SIGNAL_HOLD, } irq_signal_t; -extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal); +extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, + irq_signal_t signal); typedef enum { IRQ_LEVEL_LOW, @@ -50,23 +51,6 @@ typedef enum { extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level); -typedef enum { - GPIO_DATA_LOW, - GPIO_DATA_HIGH, - GPIO_DATA_INVAL, -} gpio_data_t; - -extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin); -extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data); - -typedef enum { - GPIO_INPUT, - GPIO_OUTPUT, - GPIO_OUTPUT_DISABLE, -} gpio_direction_t; - -extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir); - typedef enum { GPIO_PULL_DOWN, GPIO_PULL_UP, diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0bd01f49cfd8b..6a06913b01d30 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -1029,10 +1029,6 @@ config CS5535_GPIO If compiled as a module, it will be called cs5535_gpio. -config GPIO_VR41XX - tristate "NEC VR4100 series General-purpose I/O Unit support" - depends on CPU_VR41XX - config RAW_DRIVER tristate "RAW driver (/dev/raw/rawN)" depends on BLOCK diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 189efcff08ce2..66f779ad4f4c0 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o -obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o obj-$(CONFIG_GPIO_TB0219) += tb0219.o obj-$(CONFIG_TELCLOCK) += tlclk.o diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 54c837288d194..e69de29bb2d1d 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c @@ -1,680 +0,0 @@ -/* - * Driver for NEC VR4100 series General-purpose I/O Unit. - * - * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/smp_lock.h> -#include <linux/spinlock.h> -#include <linux/types.h> - -#include <asm/io.h> -#include <asm/vr41xx/giu.h> -#include <asm/vr41xx/irq.h> -#include <asm/vr41xx/vr41xx.h> - -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); -MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); -MODULE_LICENSE("GPL"); - -static int major; /* default is dynamic major device number */ -module_param(major, int, 0); -MODULE_PARM_DESC(major, "Major device number"); - -#define GIUIOSELL 0x00 -#define GIUIOSELH 0x02 -#define GIUPIODL 0x04 -#define GIUPIODH 0x06 -#define GIUINTSTATL 0x08 -#define GIUINTSTATH 0x0a -#define GIUINTENL 0x0c -#define GIUINTENH 0x0e -#define GIUINTTYPL 0x10 -#define GIUINTTYPH 0x12 -#define GIUINTALSELL 0x14 -#define GIUINTALSELH 0x16 -#define GIUINTHTSELL 0x18 -#define GIUINTHTSELH 0x1a -#define GIUPODATL 0x1c -#define GIUPODATEN 0x1c -#define GIUPODATH 0x1e - #define PIOEN0 0x0100 - #define PIOEN1 0x0200 -#define GIUPODAT 0x1e -#define GIUFEDGEINHL 0x20 -#define GIUFEDGEINHH 0x22 -#define GIUREDGEINHL 0x24 -#define GIUREDGEINHH 0x26 - -#define GIUUSEUPDN 0x1e0 -#define GIUTERMUPDN 0x1e2 - -#define GPIO_HAS_PULLUPDOWN_IO 0x0001 -#define GPIO_HAS_OUTPUT_ENABLE 0x0002 -#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 - -static spinlock_t giu_lock; -static unsigned long giu_flags; -static unsigned int giu_nr_pins; - -static void __iomem *giu_base; - -#define giu_read(offset) readw(giu_base + (offset)) -#define giu_write(offset, value) writew((value), giu_base + (offset)) - -#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) -#define GIUINT_HIGH_OFFSET 16 -#define GIUINT_HIGH_MAX 32 - -static inline uint16_t giu_set(uint16_t offset, uint16_t set) -{ - uint16_t data; - - data = giu_read(offset); - data |= set; - giu_write(offset, data); - - return data; -} - -static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) -{ - uint16_t data; - - data = giu_read(offset); - data &= ~clear; - giu_write(offset, data); - - return data; -} - -static void ack_giuint_low(unsigned int irq) -{ - giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static void mask_giuint_low(unsigned int irq) -{ - giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static void mask_ack_giuint_low(unsigned int irq) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq); - giu_clear(GIUINTENL, 1 << pin); - giu_write(GIUINTSTATL, 1 << pin); -} - -static void unmask_giuint_low(unsigned int irq) -{ - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); -} - -static struct irq_chip giuint_low_irq_chip = { - .name = "GIUINTL", - .ack = ack_giuint_low, - .mask = mask_giuint_low, - .mask_ack = mask_ack_giuint_low, - .unmask = unmask_giuint_low, -}; - -static void ack_giuint_high(unsigned int irq) -{ - giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_giuint_high(unsigned int irq) -{ - giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static void mask_ack_giuint_high(unsigned int irq) -{ - unsigned int pin; - - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; - giu_clear(GIUINTENH, 1 << pin); - giu_write(GIUINTSTATH, 1 << pin); -} - -static void unmask_giuint_high(unsigned int irq) -{ - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); -} - -static struct irq_chip giuint_high_irq_chip = { - .name = "GIUINTH", - .ack = ack_giuint_high, - .mask = mask_giuint_high, - .mask_ack = mask_ack_giuint_high, - .unmask = unmask_giuint_high, -}; - -static int giu_get_irq(unsigned int irq) -{ - uint16_t pendl, pendh, maskl, maskh; - int i; - - pendl = giu_read(GIUINTSTATL); - pendh = giu_read(GIUINTSTATH); - maskl = giu_read(GIUINTENL); - maskh = giu_read(GIUINTENH); - - maskl &= pendl; - maskh &= pendh; - - if (maskl) { - for (i = 0; i < 16; i++) { - if (maskl & (1 << i)) - return GIU_IRQ(i); - } - } else if (maskh) { - for (i = 0; i < 16; i++) { - if (maskh & (1 << i)) - return GIU_IRQ(i + GIUINT_HIGH_OFFSET); - } - } - - printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", - maskl, pendl, maskh, pendh); - - atomic_inc(&irq_err_count); - - return -EINVAL; -} - -void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) -{ - uint16_t mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPL, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELL, mask); - else - giu_clear(GIUINTHTSELL, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHL, mask); - giu_clear(GIUREDGEINHL, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - default: - giu_set(GIUFEDGEINHL, mask); - giu_set(GIUREDGEINHL, mask); - break; - } - } - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPL, mask); - giu_clear(GIUINTHTSELL, mask); - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_low_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (trigger != IRQ_TRIGGER_LEVEL) { - giu_set(GIUINTTYPH, mask); - if (signal == IRQ_SIGNAL_HOLD) - giu_set(GIUINTHTSELH, mask); - else - giu_clear(GIUINTHTSELH, mask); - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { - switch (trigger) { - case IRQ_TRIGGER_EDGE_FALLING: - giu_set(GIUFEDGEINHH, mask); - giu_clear(GIUREDGEINHH, mask); - break; - case IRQ_TRIGGER_EDGE_RISING: - giu_clear(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - default: - giu_set(GIUFEDGEINHH, mask); - giu_set(GIUREDGEINHH, mask); - break; - } - } - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_edge_irq); - } else { - giu_clear(GIUINTTYPH, mask); - giu_clear(GIUINTHTSELH, mask); - set_irq_chip_and_handler(GIU_IRQ(pin), - &giuint_high_irq_chip, - handle_level_irq); - } - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); - -void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) -{ - uint16_t mask; - - if (pin < GIUINT_HIGH_OFFSET) { - mask = 1 << pin; - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELL, mask); - else - giu_clear(GIUINTALSELL, mask); - giu_write(GIUINTSTATL, mask); - } else if (pin < GIUINT_HIGH_MAX) { - mask = 1 << (pin - GIUINT_HIGH_OFFSET); - if (level == IRQ_LEVEL_HIGH) - giu_set(GIUINTALSELH, mask); - else - giu_clear(GIUINTALSELH, mask); - giu_write(GIUINTSTATH, mask); - } -} -EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); - -gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) -{ - uint16_t reg, mask; - - if (pin >= giu_nr_pins) - return GPIO_DATA_INVAL; - - if (pin < 16) { - reg = giu_read(GIUPIODL); - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - reg = giu_read(GIUPIODH); - mask = (uint16_t)1 << (pin - 16); - } else if (pin < 48) { - reg = giu_read(GIUPODATL); - mask = (uint16_t)1 << (pin - 32); - } else { - reg = giu_read(GIUPODATH); - mask = (uint16_t)1 << (pin - 48); - } - - if (reg & mask) - return GPIO_DATA_HIGH; - - return GPIO_DATA_LOW; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); - -int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) -{ - uint16_t offset, mask, reg; - unsigned long flags; - - if (pin >= giu_nr_pins) - return -EINVAL; - - if (pin < 16) { - offset = GIUPIODL; - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - offset = GIUPIODH; - mask = (uint16_t)1 << (pin - 16); - } else if (pin < 48) { - offset = GIUPODATL; - mask = (uint16_t)1 << (pin - 32); - } else { - offset = GIUPODATH; - mask = (uint16_t)1 << (pin - 48); - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (data == GPIO_DATA_HIGH) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); - -int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) -{ - uint16_t offset, mask, reg; - unsigned long flags; - - if (pin >= giu_nr_pins) - return -EINVAL; - - if (pin < 16) { - offset = GIUIOSELL; - mask = (uint16_t)1 << pin; - } else if (pin < 32) { - offset = GIUIOSELH; - mask = (uint16_t)1 << (pin - 16); - } else { - if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { - offset = GIUPODATEN; - mask = (uint16_t)1 << (pin - 32); - } else { - switch (pin) { - case 48: - offset = GIUPODATH; - mask = PIOEN0; - break; - case 49: - offset = GIUPODATH; - mask = PIOEN1; - break; - default: - return -EINVAL; - } - } - } - - spin_lock_irqsave(&giu_lock, flags); - - reg = giu_read(offset); - if (dir == GPIO_OUTPUT) - reg |= mask; - else - reg &= ~mask; - giu_write(offset, reg); - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); - -int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) -{ - uint16_t reg, mask; - unsigned long flags; - - if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) - return -EPERM; - - if (pin >= 15) - return -EINVAL; - - mask = (uint16_t)1 << pin; - - spin_lock_irqsave(&giu_lock, flags); - - if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { - reg = giu_read(GIUTERMUPDN); - if (pull == GPIO_PULL_UP) - reg |= mask; - else - reg &= ~mask; - giu_write(GIUTERMUPDN, reg); - - reg = giu_read(GIUUSEUPDN); - reg |= mask; - giu_write(GIUUSEUPDN, reg); - } else { - reg = giu_read(GIUUSEUPDN); - reg &= ~mask; - giu_write(GIUUSEUPDN, reg); - } - - spin_unlock_irqrestore(&giu_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); - -static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, - loff_t *ppos) -{ - unsigned int pin; - char value = '0'; - - pin = iminor(file->f_path.dentry->d_inode); - if (pin >= giu_nr_pins) - return -EBADF; - - if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) - value = '1'; - - if (len <= 0) - return -EFAULT; - - if (put_user(value, buf)) - return -EFAULT; - - return 1; -} - -static ssize_t gpio_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - unsigned int pin; - size_t i; - char c; - int retval = 0; - - pin = iminor(file->f_path.dentry->d_inode); - if (pin >= giu_nr_pins) - return -EBADF; - - for (i = 0; i < len; i++) { - if (get_user(c, data + i)) - return -EFAULT; - - switch (c) { - case '0': - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); - break; - case '1': - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); - break; - case 'D': - printk(KERN_INFO "GPIO%d: pull down\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); - break; - case 'd': - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); - break; - case 'I': - printk(KERN_INFO "GPIO%d: input\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); - break; - case 'O': - printk(KERN_INFO "GPIO%d: output\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); - break; - case 'o': - printk(KERN_INFO "GPIO%d: output disable\n", pin); - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); - break; - case 'P': - printk(KERN_INFO "GPIO%d: pull up\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); - break; - case 'p': - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); - break; - default: - break; - } - - if (retval < 0) - break; - } - - return i; -} - -static int gpio_open(struct inode *inode, struct file *file) -{ - unsigned int pin; - - cycle_kernel_lock(); - pin = iminor(inode); - if (pin >= giu_nr_pins) - return -EBADF; - - return nonseekable_open(inode, file); -} - -static int gpio_release(struct inode *inode, struct file *file) -{ - unsigned int pin; - - pin = iminor(inode); - if (pin >= giu_nr_pins) - return -EBADF; - - return 0; -} - -static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .read = gpio_read, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, -}; - -static int __devinit giu_probe(struct platform_device *dev) -{ - struct resource *res; - unsigned int trigger, i, pin; - struct irq_chip *chip; - int irq, retval; - - switch (dev->id) { - case GPIO_50PINS_PULLUPDOWN: - giu_flags = GPIO_HAS_PULLUPDOWN_IO; - giu_nr_pins = 50; - break; - case GPIO_36PINS: - giu_nr_pins = 36; - break; - case GPIO_48PINS_EDGE_SELECT: - giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; - giu_nr_pins = 48; - break; - default: - printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); - return -ENODEV; - } - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!res) - return -EBUSY; - - giu_base = ioremap(res->start, res->end - res->start + 1); - if (!giu_base) - return -ENOMEM; - - retval = register_chrdev(major, "GIU", &gpio_fops); - if (retval < 0) { - iounmap(giu_base); - giu_base = NULL; - return retval; - } - - if (major == 0) { - major = retval; - printk(KERN_INFO "GIU: major number %d\n", major); - } - - spin_lock_init(&giu_lock); - - giu_write(GIUINTENL, 0); - giu_write(GIUINTENH, 0); - - trigger = giu_read(GIUINTTYPH) << 16; - trigger |= giu_read(GIUINTTYPL); - for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { - pin = GPIO_PIN_OF_IRQ(i); - if (pin < GIUINT_HIGH_OFFSET) - chip = &giuint_low_irq_chip; - else - chip = &giuint_high_irq_chip; - - if (trigger & (1 << pin)) - set_irq_chip_and_handler(i, chip, handle_edge_irq); - else - set_irq_chip_and_handler(i, chip, handle_level_irq); - - } - - irq = platform_get_irq(dev, 0); - if (irq < 0 || irq >= nr_irqs) - return -EBUSY; - - return cascade_irq(irq, giu_get_irq); -} - -static int __devexit giu_remove(struct platform_device *dev) -{ - if (giu_base) { - iounmap(giu_base); - giu_base = NULL; - } - - return 0; -} - -static struct platform_driver giu_device_driver = { - .probe = giu_probe, - .remove = __devexit_p(giu_remove), - .driver = { - .name = "GIU", - .owner = THIS_MODULE, - }, -}; - -static int __init vr41xx_giu_init(void) -{ - return platform_driver_register(&giu_device_driver); -} - -static void __exit vr41xx_giu_exit(void) -{ - platform_driver_unregister(&giu_device_driver); -} - -module_init(vr41xx_giu_init); -module_exit(vr41xx_giu_exit); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3582c39f97258..96dda81c92285 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -79,6 +79,12 @@ config GPIO_XILINX help Say yes here to support the Xilinx FPGA GPIO device +config GPIO_VR41XX + tristate "NEC VR4100 series General-purpose I/O Uint support" + depends on CPU_VR41XX + help + Say yes here to support the NEC VR4100 series General-purpose I/O Uint + comment "I2C GPIO expanders:" config GPIO_MAX732X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ef90203e8f3c7..9244c6fcd8be3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o +obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c new file mode 100644 index 0000000000000..f691ffa95fbb1 --- /dev/null +++ b/drivers/gpio/vr41xx_giu.c @@ -0,0 +1,586 @@ +/* + * Driver for NEC VR4100 series General-purpose I/O Unit. + * + * Copyright (C) 2002 MontaVista Software Inc. + * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> + * Copyright (C) 2003-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/smp_lock.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +#include <asm/vr41xx/giu.h> +#include <asm/vr41xx/irq.h> +#include <asm/vr41xx/vr41xx.h> + +MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); +MODULE_LICENSE("GPL"); + +#define GIUIOSELL 0x00 +#define GIUIOSELH 0x02 +#define GIUPIODL 0x04 +#define GIUPIODH 0x06 +#define GIUINTSTATL 0x08 +#define GIUINTSTATH 0x0a +#define GIUINTENL 0x0c +#define GIUINTENH 0x0e +#define GIUINTTYPL 0x10 +#define GIUINTTYPH 0x12 +#define GIUINTALSELL 0x14 +#define GIUINTALSELH 0x16 +#define GIUINTHTSELL 0x18 +#define GIUINTHTSELH 0x1a +#define GIUPODATL 0x1c +#define GIUPODATEN 0x1c +#define GIUPODATH 0x1e + #define PIOEN0 0x0100 + #define PIOEN1 0x0200 +#define GIUPODAT 0x1e +#define GIUFEDGEINHL 0x20 +#define GIUFEDGEINHH 0x22 +#define GIUREDGEINHL 0x24 +#define GIUREDGEINHH 0x26 + +#define GIUUSEUPDN 0x1e0 +#define GIUTERMUPDN 0x1e2 + +#define GPIO_HAS_PULLUPDOWN_IO 0x0001 +#define GPIO_HAS_OUTPUT_ENABLE 0x0002 +#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 + +enum { + GPIO_INPUT, + GPIO_OUTPUT, +}; + +static DEFINE_SPINLOCK(giu_lock); +static unsigned long giu_flags; + +static void __iomem *giu_base; + +#define giu_read(offset) readw(giu_base + (offset)) +#define giu_write(offset, value) writew((value), giu_base + (offset)) + +#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) +#define GIUINT_HIGH_OFFSET 16 +#define GIUINT_HIGH_MAX 32 + +static inline u16 giu_set(u16 offset, u16 set) +{ + u16 data; + + data = giu_read(offset); + data |= set; + giu_write(offset, data); + + return data; +} + +static inline u16 giu_clear(u16 offset, u16 clear) +{ + u16 data; + + data = giu_read(offset); + data &= ~clear; + giu_write(offset, data); + + return data; +} + +static void ack_giuint_low(unsigned int irq) +{ + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static void mask_giuint_low(unsigned int irq) +{ + giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static void mask_ack_giuint_low(unsigned int irq) +{ + unsigned int pin; + + pin = GPIO_PIN_OF_IRQ(irq); + giu_clear(GIUINTENL, 1 << pin); + giu_write(GIUINTSTATL, 1 << pin); +} + +static void unmask_giuint_low(unsigned int irq) +{ + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); +} + +static struct irq_chip giuint_low_irq_chip = { + .name = "GIUINTL", + .ack = ack_giuint_low, + .mask = mask_giuint_low, + .mask_ack = mask_ack_giuint_low, + .unmask = unmask_giuint_low, +}; + +static void ack_giuint_high(unsigned int irq) +{ + giu_write(GIUINTSTATH, + 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static void mask_giuint_high(unsigned int irq) +{ + giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static void mask_ack_giuint_high(unsigned int irq) +{ + unsigned int pin; + + pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; + giu_clear(GIUINTENH, 1 << pin); + giu_write(GIUINTSTATH, 1 << pin); +} + +static void unmask_giuint_high(unsigned int irq) +{ + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); +} + +static struct irq_chip giuint_high_irq_chip = { + .name = "GIUINTH", + .ack = ack_giuint_high, + .mask = mask_giuint_high, + .mask_ack = mask_ack_giuint_high, + .unmask = unmask_giuint_high, +}; + +static int giu_get_irq(unsigned int irq) +{ + u16 pendl, pendh, maskl, maskh; + int i; + + pendl = giu_read(GIUINTSTATL); + pendh = giu_read(GIUINTSTATH); + maskl = giu_read(GIUINTENL); + maskh = giu_read(GIUINTENH); + + maskl &= pendl; + maskh &= pendh; + + if (maskl) { + for (i = 0; i < 16; i++) { + if (maskl & (1 << i)) + return GIU_IRQ(i); + } + } else if (maskh) { + for (i = 0; i < 16; i++) { + if (maskh & (1 << i)) + return GIU_IRQ(i + GIUINT_HIGH_OFFSET); + } + } + + printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", + maskl, pendl, maskh, pendh); + + atomic_inc(&irq_err_count); + + return -EINVAL; +} + +void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, + irq_signal_t signal) +{ + u16 mask; + + if (pin < GIUINT_HIGH_OFFSET) { + mask = 1 << pin; + if (trigger != IRQ_TRIGGER_LEVEL) { + giu_set(GIUINTTYPL, mask); + if (signal == IRQ_SIGNAL_HOLD) + giu_set(GIUINTHTSELL, mask); + else + giu_clear(GIUINTHTSELL, mask); + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { + switch (trigger) { + case IRQ_TRIGGER_EDGE_FALLING: + giu_set(GIUFEDGEINHL, mask); + giu_clear(GIUREDGEINHL, mask); + break; + case IRQ_TRIGGER_EDGE_RISING: + giu_clear(GIUFEDGEINHL, mask); + giu_set(GIUREDGEINHL, mask); + break; + default: + giu_set(GIUFEDGEINHL, mask); + giu_set(GIUREDGEINHL, mask); + break; + } + } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_edge_irq); + } else { + giu_clear(GIUINTTYPL, mask); + giu_clear(GIUINTHTSELL, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_low_irq_chip, + handle_level_irq); + } + giu_write(GIUINTSTATL, mask); + } else if (pin < GIUINT_HIGH_MAX) { + mask = 1 << (pin - GIUINT_HIGH_OFFSET); + if (trigger != IRQ_TRIGGER_LEVEL) { + giu_set(GIUINTTYPH, mask); + if (signal == IRQ_SIGNAL_HOLD) + giu_set(GIUINTHTSELH, mask); + else + giu_clear(GIUINTHTSELH, mask); + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { + switch (trigger) { + case IRQ_TRIGGER_EDGE_FALLING: + giu_set(GIUFEDGEINHH, mask); + giu_clear(GIUREDGEINHH, mask); + break; + case IRQ_TRIGGER_EDGE_RISING: + giu_clear(GIUFEDGEINHH, mask); + giu_set(GIUREDGEINHH, mask); + break; + default: + giu_set(GIUFEDGEINHH, mask); + giu_set(GIUREDGEINHH, mask); + break; + } + } + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_edge_irq); + } else { + giu_clear(GIUINTTYPH, mask); + giu_clear(GIUINTHTSELH, mask); + set_irq_chip_and_handler(GIU_IRQ(pin), + &giuint_high_irq_chip, + handle_level_irq); + } + giu_write(GIUINTSTATH, mask); + } +} +EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); + +void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) +{ + u16 mask; + + if (pin < GIUINT_HIGH_OFFSET) { + mask = 1 << pin; + if (level == IRQ_LEVEL_HIGH) + giu_set(GIUINTALSELL, mask); + else + giu_clear(GIUINTALSELL, mask); + giu_write(GIUINTSTATL, mask); + } else if (pin < GIUINT_HIGH_MAX) { + mask = 1 << (pin - GIUINT_HIGH_OFFSET); + if (level == IRQ_LEVEL_HIGH) + giu_set(GIUINTALSELH, mask); + else + giu_clear(GIUINTALSELH, mask); + giu_write(GIUINTSTATH, mask); + } +} +EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); + +static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) +{ + u16 offset, mask, reg; + unsigned long flags; + + if (pin >= chip->ngpio) + return -EINVAL; + + if (pin < 16) { + offset = GIUIOSELL; + mask = 1 << pin; + } else if (pin < 32) { + offset = GIUIOSELH; + mask = 1 << (pin - 16); + } else { + if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { + offset = GIUPODATEN; + mask = 1 << (pin - 32); + } else { + switch (pin) { + case 48: + offset = GIUPODATH; + mask = PIOEN0; + break; + case 49: + offset = GIUPODATH; + mask = PIOEN1; + break; + default: + return -EINVAL; + } + } + } + + spin_lock_irqsave(&giu_lock, flags); + + reg = giu_read(offset); + if (dir == GPIO_OUTPUT) + reg |= mask; + else + reg &= ~mask; + giu_write(offset, reg); + + spin_unlock_irqrestore(&giu_lock, flags); + + return 0; +} + +int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) +{ + u16 reg, mask; + unsigned long flags; + + if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) + return -EPERM; + + if (pin >= 15) + return -EINVAL; + + mask = 1 << pin; + + spin_lock_irqsave(&giu_lock, flags); + + if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { + reg = giu_read(GIUTERMUPDN); + if (pull == GPIO_PULL_UP) + reg |= mask; + else + reg &= ~mask; + giu_write(GIUTERMUPDN, reg); + + reg = giu_read(GIUUSEUPDN); + reg |= mask; + giu_write(GIUUSEUPDN, reg); + } else { + reg = giu_read(GIUUSEUPDN); + reg &= ~mask; + giu_write(GIUUSEUPDN, reg); + } + + spin_unlock_irqrestore(&giu_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); + +static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) +{ + u16 reg, mask; + + if (pin >= chip->ngpio) + return -EINVAL; + + if (pin < 16) { + reg = giu_read(GIUPIODL); + mask = 1 << pin; + } else if (pin < 32) { + reg = giu_read(GIUPIODH); + mask = 1 << (pin - 16); + } else if (pin < 48) { + reg = giu_read(GIUPODATL); + mask = 1 << (pin - 32); + } else { + reg = giu_read(GIUPODATH); + mask = 1 << (pin - 48); + } + + if (reg & mask) + return 1; + + return 0; +} + +static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, + int value) +{ + u16 offset, mask, reg; + unsigned long flags; + + if (pin >= chip->ngpio) + return; + + if (pin < 16) { + offset = GIUPIODL; + mask = 1 << pin; + } else if (pin < 32) { + offset = GIUPIODH; + mask = 1 << (pin - 16); + } else if (pin < 48) { + offset = GIUPODATL; + mask = 1 << (pin - 32); + } else { + offset = GIUPODATH; + mask = 1 << (pin - 48); + } + + spin_lock_irqsave(&giu_lock, flags); + + reg = giu_read(offset); + if (value) + reg |= mask; + else + reg &= ~mask; + giu_write(offset, reg); + + spin_unlock_irqrestore(&giu_lock, flags); +} + + +static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return giu_set_direction(chip, offset, GPIO_INPUT); +} + +static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + vr41xx_gpio_set(chip, offset, value); + + return giu_set_direction(chip, offset, GPIO_OUTPUT); +} + +static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + if (offset >= chip->ngpio) + return -EINVAL; + + return GIU_IRQ_BASE + offset; +} + +static struct gpio_chip vr41xx_gpio_chip = { + .label = "vr41xx", + .owner = THIS_MODULE, + .direction_input = vr41xx_gpio_direction_input, + .get = vr41xx_gpio_get, + .direction_output = vr41xx_gpio_direction_output, + .set = vr41xx_gpio_set, + .to_irq = vr41xx_gpio_to_irq, +}; + +static int __devinit giu_probe(struct platform_device *pdev) +{ + struct resource *res; + unsigned int trigger, i, pin; + struct irq_chip *chip; + int irq, retval; + + switch (pdev->id) { + case GPIO_50PINS_PULLUPDOWN: + giu_flags = GPIO_HAS_PULLUPDOWN_IO; + vr41xx_gpio_chip.ngpio = 50; + break; + case GPIO_36PINS: + vr41xx_gpio_chip.ngpio = 36; + break; + case GPIO_48PINS_EDGE_SELECT: + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; + vr41xx_gpio_chip.ngpio = 48; + break; + default: + dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EBUSY; + + giu_base = ioremap(res->start, res->end - res->start + 1); + if (!giu_base) + return -ENOMEM; + + vr41xx_gpio_chip.dev = &pdev->dev; + + retval = gpiochip_add(&vr41xx_gpio_chip); + + giu_write(GIUINTENL, 0); + giu_write(GIUINTENH, 0); + + trigger = giu_read(GIUINTTYPH) << 16; + trigger |= giu_read(GIUINTTYPL); + for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { + pin = GPIO_PIN_OF_IRQ(i); + if (pin < GIUINT_HIGH_OFFSET) + chip = &giuint_low_irq_chip; + else + chip = &giuint_high_irq_chip; + + if (trigger & (1 << pin)) + set_irq_chip_and_handler(i, chip, handle_edge_irq); + else + set_irq_chip_and_handler(i, chip, handle_level_irq); + + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0 || irq >= nr_irqs) + return -EBUSY; + + return cascade_irq(irq, giu_get_irq); +} + +static int __devexit giu_remove(struct platform_device *pdev) +{ + if (giu_base) { + iounmap(giu_base); + giu_base = NULL; + } + + return 0; +} + +static struct platform_driver giu_device_driver = { + .probe = giu_probe, + .remove = __devexit_p(giu_remove), + .driver = { + .name = "GIU", + .owner = THIS_MODULE, + }, +}; + +static int __init vr41xx_giu_init(void) +{ + return platform_driver_register(&giu_device_driver); +} + +static void __exit vr41xx_giu_exit(void) +{ + platform_driver_unregister(&giu_device_driver); +} + +module_init(vr41xx_giu_init); +module_exit(vr41xx_giu_exit); -- GitLab From b53d4d1f8d522342e66f79b8b49a19835071fed4 Mon Sep 17 00:00:00 2001 From: David Daney <ddaney@caviumnetworks.com> Date: Mon, 29 Jun 2009 09:54:15 -0700 Subject: [PATCH 0638/1002] MIPS: Define __arch_swab64 for all mips r2 cpus Some CPUs implement mipsr2, but because they are a super-set of mips64r2 do not define CONFIG_CPU_MIPS64_R2. Cavium OCTEON falls into this category. We would still like to use the optimized implementation, so since we have already checked for CONFIG_CPU_MIPSR2, checking for CONFIG_64BIT instead of CONFIG_CPU_MIPS64_R2 is sufficient. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/swab.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/swab.h b/arch/mips/include/asm/swab.h index 99993c0d6c12b..97c2f81b4b43a 100644 --- a/arch/mips/include/asm/swab.h +++ b/arch/mips/include/asm/swab.h @@ -38,7 +38,11 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) } #define __arch_swab32 __arch_swab32 -#ifdef CONFIG_CPU_MIPS64_R2 +/* + * Having already checked for CONFIG_CPU_MIPSR2, enable the + * optimized version for 64-bit kernel on r2 CPUs. + */ +#ifdef CONFIG_64BIT static inline __attribute_const__ __u64 __arch_swab64(__u64 x) { __asm__( @@ -50,6 +54,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x) return x; } #define __arch_swab64 __arch_swab64 -#endif /* CONFIG_CPU_MIPS64_R2 */ +#endif /* CONFIG_64BIT */ #endif /* CONFIG_CPU_MIPSR2 */ #endif /* _ASM_SWAB_H */ -- GitLab From 9306c8def6abc2dbde4ac75eb6c631606b8fc1dd Mon Sep 17 00:00:00 2001 From: Tim Anderson <tanderson@mvista.com> Date: Wed, 17 Jun 2009 16:21:19 -0700 Subject: [PATCH 0639/1002] MIPS: CMP: Extend the GIC IPI interrupts beyond 32 This patch extends the GIC interrupt handling beyond the current 32 bit range as well as extending the number of interrupts based on the number of CPUs. Signed-off-by: Tim Anderson <tanderson@mvista.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/gic.h | 4 ++++ arch/mips/kernel/irq-gic.c | 15 ++++----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 954807d9d66ae..e8fdd92c52c73 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -20,7 +20,11 @@ #define GIC_TRIG_EDGE 1 #define GIC_TRIG_LEVEL 0 +#if CONFIG_SMP +#define GIC_NUM_INTRS (24 + NR_CPUS * 2) +#else #define GIC_NUM_INTRS 32 +#endif #define MSK(n) ((1 << (n)) - 1) #define REG32(addr) (*(volatile unsigned int *) (addr)) diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 39000f103f2ca..5c85e1ce0499d 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -107,9 +107,7 @@ static unsigned int gic_irq_startup(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_SET_INTR_MASK(irq, 1); return 0; } @@ -120,8 +118,7 @@ static void gic_irq_ack(unsigned int irq) #endif pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_CLR_INTR_MASK(irq, 1); if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) { if (!gic_wedgeb2bok) @@ -138,18 +135,14 @@ static void gic_mask_irq(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_CLR_INTR_MASK(irq, 1); } static void gic_unmask_irq(unsigned int irq) { pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq); irq -= _irqbase; - /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */ - GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))), - 1 << (irq % 32)); + GIC_SET_INTR_MASK(irq, 1); } #ifdef CONFIG_SMP -- GitLab From a214cef9a5d06894785dca1f967c9c324cc84c17 Mon Sep 17 00:00:00 2001 From: Tim Anderson <tanderson@mvista.com> Date: Wed, 17 Jun 2009 16:22:25 -0700 Subject: [PATCH 0640/1002] MIPS: CMP: Extend IPI handling to CPU number This takes the current IPI interrupt assignment from the fix number of 4 to the number of CPUs defined in the system. Signed-off-by: Tim Anderson <tanderson@mvista.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/kernel/irq-gic.c | 4 ++ arch/mips/mti-malta/malta-int.c | 74 ++++++++++++++++----------------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 5c85e1ce0499d..d2072cd385922 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -247,6 +247,10 @@ static void __init gic_basic_init(void) if (cpu == X) continue; + if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 && + _intrmap[i].ipiflag == 0) + continue; + setup_intr(_intrmap[i].intrnum, _intrmap[i].cpunum, _intrmap[i].pin, diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index b4eaf137e4a71..4e14972dcfc44 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -331,6 +331,11 @@ static struct irqaction irq_call = { .flags = IRQF_DISABLED|IRQF_PERCPU, .name = "IPI_call" }; + +static int gic_resched_int_base; +static int gic_call_int_base; +#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) +#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) #endif /* CONFIG_MIPS_MT_SMP */ static struct irqaction i8259irq = { @@ -370,7 +375,7 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); * Interrupts and CPUs/Core Interrupts. The nature of the External * Interrupts is also defined here - polarity/trigger. */ -static struct gic_intr_map gic_intr_map[] = { +static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { { GIC_EXT_INTR(0), X, X, X, X, 0 }, { GIC_EXT_INTR(1), X, X, X, X, 0 }, { GIC_EXT_INTR(2), X, X, X, X, 0 }, @@ -387,14 +392,7 @@ static struct gic_intr_map gic_intr_map[] = { { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, { GIC_EXT_INTR(15), X, X, X, X, 0 }, - { GIC_EXT_INTR(16), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(17), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(18), 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(19), 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(20), 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(21), 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(22), 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, - { GIC_EXT_INTR(23), 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, +/* This is the end of the general interrupts now we do IPI ones */ }; #endif @@ -416,14 +414,25 @@ static int __init gcmp_probe(unsigned long addr, unsigned long size) } #if defined(CONFIG_MIPS_MT_SMP) +static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) +{ + int intr = baseintr + cpu; + gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr); + gic_intr_map[intr].cpunum = cpu; + gic_intr_map[intr].pin = cpupin; + gic_intr_map[intr].polarity = GIC_POL_POS; + gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; + gic_intr_map[intr].ipiflag = 1; + ipi_map[cpu] |= (1 << (cpupin + 2)); +} + static void __init fill_ipi_map(void) { - int i; + int cpu; - for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) { - if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X)) - ipi_map[gic_intr_map[i].cpunum] |= - (1 << (gic_intr_map[i].pin + 2)); + for (cpu = 0; cpu < NR_CPUS; cpu++) { + fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); + fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); } } #endif @@ -514,24 +523,10 @@ void __init arch_init_irq(void) if (gic_present) { /* FIXME */ int i; - struct { - unsigned int resched; - unsigned int call; - } ipiirq[] = { - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE0}, - { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE1 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE2 - }, { - .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3, - .call = GIC_IPI_EXT_INTR_CALLFNC_VPE3 - } - }; + + gic_call_int_base = GIC_NUM_INTRS - NR_CPUS; + gic_resched_int_base = gic_call_int_base - NR_CPUS; + fill_ipi_map(); gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); if (!gcmp_present) { @@ -553,12 +548,15 @@ void __init arch_init_irq(void) printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status()); write_c0_status(0x1100dc00); printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status()); - for (i = 0; i < ARRAY_SIZE(ipiirq); i++) { - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched); - setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call); - - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq); - set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq); + for (i = 0; i < NR_CPUS; i++) { + setup_irq(MIPS_GIC_IRQ_BASE + + GIC_RESCHED_INT(i), &irq_resched); + setup_irq(MIPS_GIC_IRQ_BASE + + GIC_CALL_INT(i), &irq_call); + set_irq_handler(MIPS_GIC_IRQ_BASE + + GIC_RESCHED_INT(i), handle_percpu_irq); + set_irq_handler(MIPS_GIC_IRQ_BASE + + GIC_CALL_INT(i), handle_percpu_irq); } } else { /* set up ipi interrupts */ -- GitLab From 0365070f05f12f1648b4adf22cfb52ec7a8a371c Mon Sep 17 00:00:00 2001 From: Tim Anderson <tanderson@mvista.com> Date: Wed, 17 Jun 2009 16:22:53 -0700 Subject: [PATCH 0641/1002] MIPS: CMP: activate CMP support Most of the CMP support was added before, this mostly correct compile problems but adds a platform specific translation for the interrupt number based on cpu number. Signed-off-by: Tim Anderson <tanderson@mvista.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/amon.h | 7 ++++ arch/mips/include/asm/gic.h | 2 + arch/mips/kernel/smp-cmp.c | 66 +++------------------------------ arch/mips/mti-malta/malta-int.c | 10 +++++ 5 files changed, 25 insertions(+), 62 deletions(-) create mode 100644 arch/mips/include/asm/amon.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 64891f74019fa..4368a723e2d0f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -229,7 +229,7 @@ config MIPS_MALTA select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN - select SYS_SUPPORTS_MIPS_CMP if BROKEN # because SYNC_R4K is broken + select SYS_SUPPORTS_MIPS_CMP select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_SMARTMIPS help diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h new file mode 100644 index 0000000000000..c3dc1a68dd8d9 --- /dev/null +++ b/arch/mips/include/asm/amon.h @@ -0,0 +1,7 @@ +/* + * Amon support + */ + +int amon_cpu_avail(int); +void amon_cpu_start(int, unsigned long, unsigned long, + unsigned long, unsigned long); diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index e8fdd92c52c73..10292e37c1f71 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -487,5 +487,7 @@ extern void gic_init(unsigned long gic_base_addr, extern unsigned int gic_get_int(void); extern void gic_send_ipi(unsigned int intr); +extern unsigned int plat_ipi_call_int_xlate(unsigned int); +extern unsigned int plat_ipi_resched_int_xlate(unsigned int); #endif /* _ASM_GICREGS_H */ diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index 653be061b9ec6..ad0ff5dc4d59b 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -37,80 +37,24 @@ #include <asm/mipsregs.h> #include <asm/mipsmtregs.h> #include <asm/mips_mt.h> - -/* - * Crude manipulation of the CPU masks to control which - * which CPU's are brought online during initialisation - * - * Beware... this needs to be called after CPU discovery - * but before CPU bringup - */ -static int __init allowcpus(char *str) -{ - cpumask_t cpu_allow_map; - char buf[256]; - int len; - - cpus_clear(cpu_allow_map); - if (cpulist_parse(str, &cpu_allow_map) == 0) { - cpu_set(0, cpu_allow_map); - cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map); - len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map); - buf[len] = '\0'; - pr_debug("Allowable CPUs: %s\n", buf); - return 1; - } else - return 0; -} -__setup("allowcpus=", allowcpus); +#include <asm/amon.h> +#include <asm/gic.h> static void ipi_call_function(unsigned int cpu) { - unsigned int action = 0; - pr_debug("CPU%d: %s cpu %d status %08x\n", smp_processor_id(), __func__, cpu, read_c0_status()); - switch (cpu) { - case 0: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE0; - break; - case 1: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE1; - break; - case 2: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE2; - break; - case 3: - action = GIC_IPI_EXT_INTR_CALLFNC_VPE3; - break; - } - gic_send_ipi(action); + gic_send_ipi(plat_ipi_call_int_xlate(cpu)); } static void ipi_resched(unsigned int cpu) { - unsigned int action = 0; - pr_debug("CPU%d: %s cpu %d status %08x\n", smp_processor_id(), __func__, cpu, read_c0_status()); - switch (cpu) { - case 0: - action = GIC_IPI_EXT_INTR_RESCHED_VPE0; - break; - case 1: - action = GIC_IPI_EXT_INTR_RESCHED_VPE1; - break; - case 2: - action = GIC_IPI_EXT_INTR_RESCHED_VPE2; - break; - case 3: - action = GIC_IPI_EXT_INTR_RESCHED_VPE3; - break; - } - gic_send_ipi(action); + gic_send_ipi(plat_ipi_resched_int_xlate(cpu)); } /* @@ -206,7 +150,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle) (unsigned long)(gp + sizeof(struct thread_info))); #endif - amon_cpu_start(cpu, pc, sp, gp, a0); + amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0); } /* diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 4e14972dcfc44..bc0ba58acfd5d 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -336,6 +336,16 @@ static int gic_resched_int_base; static int gic_call_int_base; #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) + +unsigned int plat_ipi_call_int_xlate(unsigned int cpu) +{ + return GIC_CALL_INT(cpu); +} + +unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) +{ + return GIC_RESCHED_INT(cpu); +} #endif /* CONFIG_MIPS_MT_SMP */ static struct irqaction i8259irq = { -- GitLab From 47b178bb69ea4d0043f2df509c714bc5b287f375 Mon Sep 17 00:00:00 2001 From: Tim Anderson <tanderson@mvista.com> Date: Wed, 17 Jun 2009 16:25:18 -0700 Subject: [PATCH 0642/1002] MIPS: CMP: Move gcmp_probe to before the SMP ops This is to move the gcmp_probe call to before the use of and selection of the smp_ops functions. This allows malta with 1004K to work. Signed-off-by: Tim Anderson <tanderson@mvista.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/gcmpregs.h | 2 ++ arch/mips/mti-malta/malta-init.c | 14 +++++++++++++- arch/mips/mti-malta/malta-int.c | 5 +---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h index d74a8a4ca861a..36fd969d64d6f 100644 --- a/arch/mips/include/asm/gcmpregs.h +++ b/arch/mips/include/asm/gcmpregs.h @@ -114,4 +114,6 @@ #define GCMP_CCB_DINTGROUP_OFS 0x0030 /* DINT Group Participate */ #define GCMP_CCB_DBGGROUP_OFS 0x0100 /* DebugBreak Group */ +extern int __init gcmp_probe(unsigned long, unsigned long); + #endif /* _ASM_GCMPREGS_H */ diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 475038a141a65..27c807b67feaf 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -30,6 +30,7 @@ #include <asm/cacheflush.h> #include <asm/traps.h> +#include <asm/gcmpregs.h> #include <asm/mips-boards/prom.h> #include <asm/mips-boards/generic.h> #include <asm/mips-boards/bonito64.h> @@ -192,6 +193,8 @@ extern struct plat_smp_ops msmtc_smp_ops; void __init prom_init(void) { + int result; + prom_argc = fw_arg0; _prom_argv = (int *) fw_arg1; _prom_envp = (int *) fw_arg2; @@ -358,12 +361,21 @@ void __init prom_init(void) #ifdef CONFIG_SERIAL_8250_CONSOLE console_config(); #endif + /* Early detection of CMP support */ + result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); + #ifdef CONFIG_MIPS_CMP - register_smp_ops(&cmp_smp_ops); + if (result) + register_smp_ops(&cmp_smp_ops); #endif #ifdef CONFIG_MIPS_MT_SMP +#ifdef CONFIG_MIPS_CMP + if (!result) + register_smp_ops(&vsmp_smp_ops); +#else register_smp_ops(&vsmp_smp_ops); #endif +#endif #ifdef CONFIG_MIPS_MT_SMTC register_smp_ops(&msmtc_smp_ops); #endif diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index bc0ba58acfd5d..a8756f82c31b9 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -409,7 +409,7 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { /* * GCMP needs to be detected before any SMP initialisation */ -static int __init gcmp_probe(unsigned long addr, unsigned long size) +int __init gcmp_probe(unsigned long addr, unsigned long size) { if (gcmp_present >= 0) return gcmp_present; @@ -449,14 +449,11 @@ static void __init fill_ipi_map(void) void __init arch_init_irq(void) { - int gic_present, gcmp_present; - init_i8259_irqs(); if (!cpu_has_veic) mips_cpu_irq_init(); - gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); if (gcmp_present) { GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK; gic_present = 1; -- GitLab From eb9b5141a9815ef898ef6b6441f733e81c272600 Mon Sep 17 00:00:00 2001 From: Tim Anderson <tanderson@mvista.com> Date: Wed, 17 Jun 2009 16:40:34 -0700 Subject: [PATCH 0643/1002] MIPS: CMP: Update sync-r4k for current kernel This revises the sync-4k so it will boot and operate since the removal of expirelo from the timer code. Signed-off-by: Tim Anderson <tanderson@mvista.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/Kconfig | 2 +- arch/mips/kernel/sync-r4k.c | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4368a723e2d0f..df1a92afa56ad 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1656,7 +1656,7 @@ config MIPS_APSP_KSPD config MIPS_CMP bool "MIPS CMP framework support" depends on SYS_SUPPORTS_MIPS_CMP - select SYNC_R4K if BROKEN + select SYNC_R4K select SYS_SUPPORTS_SMP select SYS_SUPPORTS_SCHED_SMT if SMP select WEAK_ORDERING diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 9021108eb9c1a..05dd170a83f7e 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -1,7 +1,7 @@ /* * Count register synchronisation. * - * All CPUs will have their count registers synchronised to the CPU0 expirelo + * All CPUs will have their count registers synchronised to the CPU0 next time * value. This can cause a small timewarp for CPU0. All other CPU's should * not have done anything significant (but they may have had interrupts * enabled briefly - prom_smp_finish() should not be responsible for enabling @@ -13,21 +13,22 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/r4k-timer.h> +#include <linux/cpumask.h> +#include <asm/r4k-timer.h> #include <asm/atomic.h> #include <asm/barrier.h> -#include <asm/cpumask.h> #include <asm/mipsregs.h> -static atomic_t __initdata count_start_flag = ATOMIC_INIT(0); -static atomic_t __initdata count_count_start = ATOMIC_INIT(0); -static atomic_t __initdata count_count_stop = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); +static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); #define COUNTON 100 #define NR_LOOPS 5 -void __init synchronise_count_master(void) +void __cpuinit synchronise_count_master(void) { int i; unsigned long flags; @@ -42,19 +43,20 @@ void __init synchronise_count_master(void) return; #endif - pr_info("Checking COUNT synchronization across %u CPUs: ", - num_online_cpus()); + printk(KERN_INFO "Synchronize counters across %u CPUs: ", + num_online_cpus()); local_irq_save(flags); /* * Notify the slaves that it's time to start */ + atomic_set(&count_reference, read_c0_count()); atomic_set(&count_start_flag, 1); smp_wmb(); - /* Count will be initialised to expirelo for all CPU's */ - initcount = expirelo; + /* Count will be initialised to current timer for all CPU's */ + initcount = read_c0_count(); /* * We loop a few times to get a primed instruction cache, @@ -106,7 +108,7 @@ void __init synchronise_count_master(void) printk("done.\n"); } -void __init synchronise_count_slave(void) +void __cpuinit synchronise_count_slave(void) { int i; unsigned long flags; @@ -131,8 +133,8 @@ void __init synchronise_count_slave(void) while (!atomic_read(&count_start_flag)) mb(); - /* Count will be initialised to expirelo for all CPU's */ - initcount = expirelo; + /* Count will be initialised to next expire for all CPU's */ + initcount = atomic_read(&count_reference); ncpus = num_online_cpus(); for (i = 0; i < NR_LOOPS; i++) { @@ -156,4 +158,3 @@ void __init synchronise_count_slave(void) local_irq_restore(flags); } #undef NR_LOOPS -#endif -- GitLab From ea4bbfd0048c53c24f72ef668b39f1247bc243c0 Mon Sep 17 00:00:00 2001 From: matthieu castet <castet.matthieu@free.fr> Date: Tue, 30 Jun 2009 23:04:55 +0200 Subject: [PATCH 0644/1002] MIPS: BC47xx: Fix SSB irq setup The current ssb irq setup in ssb_mipscore_init has the problem that it configures some device on some irq without checking that the irq is not taken by an other device. For example in my case PCI host is on irq 0 and IPSEC on irq 3. The current code: - store in dev->irq that IPSEC irq is 3 + 2 - do a set_irq 0->3 on PCI host But now IPSEC irq is not routed anymore to the mips code and dev->irq is wrong. This causes a problem described in [1]. This patch tries to solve the problem by making set_irq configure the device we want to take the irq on the shared irq0. The previous example becomes: - store in dev->irq that IPSEC irq is 3 + 2 - do a set_irq 0->3 on PCI host: - irq 3 is already taken by IPSEC. do a set_irq 3->0 on IPSEC I also added some code to print the irq configuration after irq setup to allow easier debugging. And I add extra checking in ssb_mips_irq to report device without irq or device with not routed irq. [1] http://www.danm.de/files/src/bcm5365p/REPORTED_DEVICES Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr> Acked-by : Michael Buesch <mb@bu3sch.de> Tested-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- drivers/ssb/driver_mipscore.c | 85 ++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3fd3e3b412b65..3c6feed46f6ea 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { static inline u32 ssb_irqflag(struct ssb_device *dev) { - return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; + u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); + if (tpsflag) + return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; + else + /* not irq supported */ + return 0x3f; +} + +static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) +{ + struct ssb_bus *bus = rdev->bus; + int i; + for (i = 0; i < bus->nr_devices; i++) { + struct ssb_device *dev; + dev = &(bus->devices[i]); + if (ssb_irqflag(dev) == irqflag) + return dev; + } + return NULL; } /* Get the MIPS IRQ assignment for a specified device. * If unassigned, 0 is returned. + * If disabled, 5 is returned. + * If not supported, 6 is returned. */ unsigned int ssb_mips_irq(struct ssb_device *dev) { struct ssb_bus *bus = dev->bus; + struct ssb_device *mdev = bus->mipscore.dev; u32 irqflag; u32 ipsflag; u32 tmp; unsigned int irq; irqflag = ssb_irqflag(dev); + if (irqflag == 0x3f) + return 6; ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); for (irq = 1; irq <= 4; irq++) { tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); if (tmp == irqflag) break; } - if (irq == 5) - irq = 0; + if (irq == 5) { + if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) + irq = 0; + } return irq; } @@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) struct ssb_device *mdev = bus->mipscore.dev; u32 irqflag = ssb_irqflag(dev); + BUG_ON(oldirq == 6); + dev->irq = irq + 2; - ssb_dprintk(KERN_INFO PFX - "set_irq: core 0x%04x, irq %d => %d\n", - dev->id.coreid, oldirq, irq); /* clear the old irq */ if (oldirq == 0) ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); - else + else if (oldirq != 5) clear_irq(bus, oldirq); /* assign the new one */ if (irq == 0) { ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); } else { + u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); + if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { + u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; + struct ssb_device *olddev = find_device(dev, oldipsflag); + if (olddev) + set_irq(olddev, 0); + } irqflag <<= ipsflag_irq_shift[irq]; - irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); + irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); ssb_write32(mdev, SSB_IPSFLAG, irqflag); } + ssb_dprintk(KERN_INFO PFX + "set_irq: core 0x%04x, irq %d => %d\n", + dev->id.coreid, oldirq+2, irq+2); +} + +static void print_irq(struct ssb_device *dev, unsigned int irq) +{ + int i; + static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; + ssb_dprintk(KERN_INFO PFX + "core 0x%04x, irq :", dev->id.coreid); + for (i = 0; i <= 6; i++) { + ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); + } + ssb_dprintk("\n"); +} + +static void dump_irq(struct ssb_bus *bus) +{ + int i; + for (i = 0; i < bus->nr_devices; i++) { + struct ssb_device *dev; + dev = &(bus->devices[i]); + print_irq(dev, ssb_mips_irq(dev)); + } } static void ssb_mips_serial_init(struct ssb_mipscore *mcore) @@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ for (irq = 2, i = 0; i < bus->nr_devices; i++) { + int mips_irq; dev = &(bus->devices[i]); - dev->irq = ssb_mips_irq(dev) + 2; + mips_irq = ssb_mips_irq(dev); + if (mips_irq > 4) + dev->irq = 0; + else + dev->irq = mips_irq + 2; + if (dev->irq > 5) + continue; switch (dev->id.coreid) { case SSB_DEV_USB11_HOST: /* shouldn't need a separate irq line for non-4710, most of them have a proper * external usb controller on the pci */ if ((bus->chip_id == 0x4710) && (irq <= 4)) { set_irq(dev, irq++); - break; } + break; /* fallthrough */ case SSB_DEV_PCI: case SSB_DEV_ETHERNET: @@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) } } } + ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); + dump_irq(bus); ssb_mips_serial_init(mcore); ssb_mips_flash_detect(mcore); -- GitLab From cad9bc69048b073023366ebb0878c1dd64a2c4d9 Mon Sep 17 00:00:00 2001 From: Yong Zhang <yong.zhang@windriver.com> Date: Wed, 1 Jul 2009 09:35:39 +0800 Subject: [PATCH 0645/1002] MIPS: 64-bit: Fix o32 core dump If an o32 process generates a core dump on a 64 bit kernel, the core file will not be correctly recognized. This is because ELF_CORE_COPY_REGS and ELF_CORE_COPY_TASK_REGS are not correctly defined for o32 and will use the default register set which would be CONFIG_64BIT in asm/elf.h. So we'll switch to use the right register defines in this situation by checking for WANT_COMPAT_REG_H and use the right defines of ELF_CORE_COPY_REGS and ELF_CORE_COPY_TASK_REGS. [Ralf: made ELF_CORE_COPY_TASK_REGS() bullet-proof against funny arguments.] Signed-off-by: Yong Zhang <yong.zhang@windriver.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/elf.h | 4 ++++ arch/mips/include/asm/reg.h | 2 +- arch/mips/kernel/binfmt_elfo32.c | 20 +++++++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index d58f128aa747b..7990694cda221 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -316,9 +316,13 @@ extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs); extern int dump_task_regs(struct task_struct *, elf_gregset_t *); extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); +#ifndef ELF_CORE_COPY_REGS #define ELF_CORE_COPY_REGS(elf_regs, regs) \ elf_dump_regs((elf_greg_t *)&(elf_regs), regs); +#endif +#ifndef ELF_CORE_COPY_TASK_REGS #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) +#endif #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \ dump_task_fpu(tsk, elf_fpregs) diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h index 634b55d7e7f6d..910e71a12466d 100644 --- a/arch/mips/include/asm/reg.h +++ b/arch/mips/include/asm/reg.h @@ -69,7 +69,7 @@ #endif -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H) #define EF_R0 0 #define EF_R1 1 diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index e1333d7319e27..ff448233dab55 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -53,6 +53,23 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) #include <asm/processor.h> + +/* + * When this file is selected, we are definitely running a 64bit kernel. + * So using the right regs define in asm/reg.h + */ +#define WANT_COMPAT_REG_H + +/* These MUST be defined before elf.h gets included */ +extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs); +#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); +#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest) \ +({ \ + int __res = 1; \ + elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk)); \ + __res; \ +}) + #include <linux/module.h> #include <linux/elfcore.h> #include <linux/compat.h> @@ -110,9 +127,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) value->tv_usec = rem / NSEC_PER_USEC; } -#undef ELF_CORE_COPY_REGS -#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); - void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs) { int i; -- GitLab From 3f5b3e17f791ba27f91fc4fdc514e7704d4d6273 Mon Sep 17 00:00:00 2001 From: Ralf Baechle <ralf@linux-mips.org> Date: Thu, 2 Jul 2009 11:48:07 +0100 Subject: [PATCH 0646/1002] MIPS: Allow suspend and hibernation again on uniprocessor kernels. Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Acked-by: Pavel Machek <pavel@ucw.cz> --- arch/mips/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index df1a92afa56ad..3ca0fe1a91231 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2168,11 +2168,11 @@ menu "Power management options" config ARCH_HIBERNATION_POSSIBLE def_bool y - depends on SYS_SUPPORTS_HOTPLUG_CPU + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP config ARCH_SUSPEND_POSSIBLE def_bool y - depends on SYS_SUPPORTS_HOTPLUG_CPU + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP source "kernel/power/Kconfig" -- GitLab From ada8e9514b5880f81cdbbd212d121380ceef7acc Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa <yuasa@linux-mips.org> Date: Fri, 3 Jul 2009 00:39:38 +0900 Subject: [PATCH 0647/1002] Update Yoichi Yuasa's e-mail address Signed-off-by: Yoichi Yuasa <yuasa@linux-mips.org> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/cobalt/buttons.c | 2 +- arch/mips/cobalt/lcd.c | 2 +- arch/mips/cobalt/led.c | 2 +- arch/mips/cobalt/mtd.c | 2 +- arch/mips/cobalt/rtc.c | 2 +- arch/mips/cobalt/serial.c | 2 +- arch/mips/cobalt/time.c | 2 +- arch/mips/gt64120/wrppmc/serial.c | 2 +- arch/mips/include/asm/ds1287.h | 2 +- arch/mips/include/asm/irq_gt641xx.h | 2 +- arch/mips/include/asm/mach-cobalt/irq.h | 2 +- arch/mips/include/asm/mach-cobalt/mach-gt64120.h | 2 +- arch/mips/include/asm/vr41xx/capcella.h | 2 +- arch/mips/include/asm/vr41xx/giu.h | 2 +- arch/mips/include/asm/vr41xx/irq.h | 2 +- arch/mips/include/asm/vr41xx/mpc30x.h | 2 +- arch/mips/include/asm/vr41xx/pci.h | 2 +- arch/mips/include/asm/vr41xx/siu.h | 2 +- arch/mips/include/asm/vr41xx/tb0219.h | 2 +- arch/mips/include/asm/vr41xx/tb0226.h | 2 +- arch/mips/include/asm/vr41xx/vr41xx.h | 2 +- arch/mips/kernel/cevt-ds1287.c | 2 +- arch/mips/kernel/cevt-gt641xx.c | 2 +- arch/mips/kernel/csrc-ioasic.c | 2 +- arch/mips/kernel/irq-gt641xx.c | 2 +- arch/mips/pci/fixup-capcella.c | 2 +- arch/mips/pci/fixup-mpc30x.c | 2 +- arch/mips/pci/fixup-tb0219.c | 2 +- arch/mips/pci/fixup-tb0226.c | 2 +- arch/mips/pci/fixup-tb0287.c | 2 +- arch/mips/pci/ops-vr41xx.c | 6 +++--- arch/mips/pci/pci-vr41xx.c | 6 +++--- arch/mips/pci/pci-vr41xx.h | 4 ++-- arch/mips/vr41xx/casio-e55/setup.c | 2 +- arch/mips/vr41xx/common/bcu.c | 8 ++++---- arch/mips/vr41xx/common/cmu.c | 8 ++++---- arch/mips/vr41xx/common/giu.c | 2 +- arch/mips/vr41xx/common/icu.c | 8 ++++---- arch/mips/vr41xx/common/init.c | 2 +- arch/mips/vr41xx/common/irq.c | 2 +- arch/mips/vr41xx/common/pmu.c | 2 +- arch/mips/vr41xx/common/rtc.c | 2 +- arch/mips/vr41xx/common/siu.c | 2 +- arch/mips/vr41xx/common/type.c | 2 +- arch/mips/vr41xx/ibm-workpad/setup.c | 2 +- drivers/char/tb0219.c | 4 ++-- drivers/gpio/vr41xx_giu.c | 6 +++--- drivers/input/misc/cobalt_btns.c | 4 ++-- drivers/leds/leds-cobalt-raq.c | 2 +- drivers/pcmcia/vrc4171_card.c | 4 ++-- drivers/pcmcia/vrc4173_cardu.c | 4 ++-- drivers/pcmcia/vrc4173_cardu.h | 2 +- drivers/rtc/rtc-vr41xx.c | 4 ++-- drivers/serial/vr41xx_siu.c | 2 +- drivers/video/cobalt_lcdfb.c | 2 +- 55 files changed, 76 insertions(+), 76 deletions(-) diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c index 9e143989c7b8b..4eaec8b46e0ce 100644 --- a/arch/mips/cobalt/buttons.c +++ b/arch/mips/cobalt/buttons.c @@ -1,7 +1,7 @@ /* * Cobalt buttons platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/lcd.c b/arch/mips/cobalt/lcd.c index 0720e4fae3112..0f1cd90f37edc 100644 --- a/arch/mips/cobalt/lcd.c +++ b/arch/mips/cobalt/lcd.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt LCD platform device. * - * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/led.c b/arch/mips/cobalt/led.c index 1c6ebd468b07f..d3ce6fa1dc74c 100644 --- a/arch/mips/cobalt/led.c +++ b/arch/mips/cobalt/led.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt LED platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/mtd.c b/arch/mips/cobalt/mtd.c index 2b088ef3839a4..691d620b6766a 100644 --- a/arch/mips/cobalt/mtd.c +++ b/arch/mips/cobalt/mtd.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt MTD device. * - * Copyright (C) 2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/rtc.c b/arch/mips/cobalt/rtc.c index e70794b8bcba8..3ab39898b4e46 100644 --- a/arch/mips/cobalt/rtc.c +++ b/arch/mips/cobalt/rtc.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt RTC platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/serial.c b/arch/mips/cobalt/serial.c index 53b8d0d6da908..7cb51f57275e5 100644 --- a/arch/mips/cobalt/serial.c +++ b/arch/mips/cobalt/serial.c @@ -1,7 +1,7 @@ /* * Registration of Cobalt UART platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/cobalt/time.c b/arch/mips/cobalt/time.c index 4a570e7145fe6..0162f9edc693c 100644 --- a/arch/mips/cobalt/time.c +++ b/arch/mips/cobalt/time.c @@ -1,7 +1,7 @@ /* * Cobalt time initialization. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/gt64120/wrppmc/serial.c b/arch/mips/gt64120/wrppmc/serial.c index 5ec1c2ffd3a5e..6f9d0858f596e 100644 --- a/arch/mips/gt64120/wrppmc/serial.c +++ b/arch/mips/gt64120/wrppmc/serial.c @@ -1,7 +1,7 @@ /* * Registration of WRPPMC UART platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/ds1287.h b/arch/mips/include/asm/ds1287.h index ba1702e86931b..3af0b8fb3b8c2 100644 --- a/arch/mips/include/asm/ds1287.h +++ b/arch/mips/include/asm/ds1287.h @@ -1,7 +1,7 @@ /* * DS1287 timer functions. * - * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/irq_gt641xx.h b/arch/mips/include/asm/irq_gt641xx.h index f9a7c3ac2e667..250a2407b599c 100644 --- a/arch/mips/include/asm/irq_gt641xx.h +++ b/arch/mips/include/asm/irq_gt641xx.h @@ -1,7 +1,7 @@ /* * Galileo/Marvell GT641xx IRQ definitions. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/mach-cobalt/irq.h b/arch/mips/include/asm/mach-cobalt/irq.h index 57c8c9ac58516..9da9acf5dcba4 100644 --- a/arch/mips/include/asm/mach-cobalt/irq.h +++ b/arch/mips/include/asm/mach-cobalt/irq.h @@ -8,7 +8,7 @@ * Copyright (C) 1997 Cobalt Microserver * Copyright (C) 1997, 2003 Ralf Baechle * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv) - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> */ #ifndef _ASM_COBALT_IRQ_H #define _ASM_COBALT_IRQ_H diff --git a/arch/mips/include/asm/mach-cobalt/mach-gt64120.h b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h index ae9c5523c7eff..f8afec3f29433 100644 --- a/arch/mips/include/asm/mach-cobalt/mach-gt64120.h +++ b/arch/mips/include/asm/mach-cobalt/mach-gt64120.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/capcella.h b/arch/mips/include/asm/vr41xx/capcella.h index e0ee05a3dfccc..fcc6569414faa 100644 --- a/arch/mips/include/asm/vr41xx/capcella.h +++ b/arch/mips/include/asm/vr41xx/capcella.h @@ -1,7 +1,7 @@ /* * capcella.h, Include file for ZAO Networks Capcella. * - * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/giu.h b/arch/mips/include/asm/vr41xx/giu.h index b369c091b0edd..6a90bc1d916b4 100644 --- a/arch/mips/include/asm/vr41xx/giu.h +++ b/arch/mips/include/asm/vr41xx/giu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series General-purpose I/O Unit. * - * Copyright (C) 2005-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2009 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/irq.h b/arch/mips/include/asm/vr41xx/irq.h index d315dfbc08f2c..b07f7321751dd 100644 --- a/arch/mips/include/asm/vr41xx/irq.h +++ b/arch/mips/include/asm/vr41xx/irq.h @@ -7,7 +7,7 @@ * Copyright (C) 2001, 2002 Paul Mundt * Copyright (C) 2002 MontaVista Software, Inc. * Copyright (C) 2002 TimeSys Corp. - * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/arch/mips/include/asm/vr41xx/mpc30x.h b/arch/mips/include/asm/vr41xx/mpc30x.h index 1d67df843dc32..130d09d8c8cbb 100644 --- a/arch/mips/include/asm/vr41xx/mpc30x.h +++ b/arch/mips/include/asm/vr41xx/mpc30x.h @@ -1,7 +1,7 @@ /* * mpc30x.h, Include file for Victor MP-C303/304. * - * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/pci.h b/arch/mips/include/asm/vr41xx/pci.h index 6fc01ce197770..c231a3d6cfd8f 100644 --- a/arch/mips/include/asm/vr41xx/pci.h +++ b/arch/mips/include/asm/vr41xx/pci.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series PCI Control Unit. * - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/siu.h b/arch/mips/include/asm/vr41xx/siu.h index da9f6e3734099..ca806bc4ddc8a 100644 --- a/arch/mips/include/asm/vr41xx/siu.h +++ b/arch/mips/include/asm/vr41xx/siu.h @@ -1,7 +1,7 @@ /* * Include file for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2005-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/tb0219.h b/arch/mips/include/asm/vr41xx/tb0219.h index dc981b4be0a40..c78e8243b447e 100644 --- a/arch/mips/include/asm/vr41xx/tb0219.h +++ b/arch/mips/include/asm/vr41xx/tb0219.h @@ -1,7 +1,7 @@ /* * tb0219.h, Include file for TANBAC TB0219. * - * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@linux-mips.org> * * Modified for TANBAC TB0219: * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> diff --git a/arch/mips/include/asm/vr41xx/tb0226.h b/arch/mips/include/asm/vr41xx/tb0226.h index de527dcfa5f31..36f5f798e4169 100644 --- a/arch/mips/include/asm/vr41xx/tb0226.h +++ b/arch/mips/include/asm/vr41xx/tb0226.h @@ -1,7 +1,7 @@ /* * tb0226.h, Include file for TANBAC TB0226. * - * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/include/asm/vr41xx/vr41xx.h b/arch/mips/include/asm/vr41xx/vr41xx.h index 22be64971cc69..7b96a43b72ba5 100644 --- a/arch/mips/include/asm/vr41xx/vr41xx.h +++ b/arch/mips/include/asm/vr41xx/vr41xx.h @@ -7,7 +7,7 @@ * Copyright (C) 2001, 2002 Paul Mundt * Copyright (C) 2002 MontaVista Software, Inc. * Copyright (C) 2002 TimeSys Corp. - * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 1ada45ea07003..6996da4d74a27 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -1,7 +1,7 @@ /* * DS1287 clockevent driver * - * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index e9b787feedcb7..92351e00ae0e2 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -1,7 +1,7 @@ /* * GT641xx clockevent routines. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c index b551f48d3a076..23da108506b0a 100644 --- a/arch/mips/kernel/csrc-ioasic.c +++ b/arch/mips/kernel/csrc-ioasic.c @@ -1,7 +1,7 @@ /* * DEC I/O ASIC's counter clocksource * - * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c index 1b81b131f43c9..ebcc5f7ad9c21 100644 --- a/arch/mips/kernel/irq-gt641xx.c +++ b/arch/mips/kernel/irq-gt641xx.c @@ -1,7 +1,7 @@ /* * GT641xx IRQ routines. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c index 1416bca6d1a3f..1c02f5737367a 100644 --- a/arch/mips/pci/fixup-capcella.c +++ b/arch/mips/pci/fixup-capcella.c @@ -1,7 +1,7 @@ /* * fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c index 5911596257222..e08f49cb6875a 100644 --- a/arch/mips/pci/fixup-mpc30x.c +++ b/arch/mips/pci/fixup-mpc30x.c @@ -1,7 +1,7 @@ /* * fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups. * - * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index ed87733f67968..8084b17d44066 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c index e3eedf4bf9bd0..4196ccf3ea3da 100644 --- a/arch/mips/pci/fixup-tb0226.c +++ b/arch/mips/pci/fixup-tb0226.c @@ -1,7 +1,7 @@ /* * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups. * - * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c index 267ab3dc3d421..2fe29db437259 100644 --- a/arch/mips/pci/fixup-tb0287.c +++ b/arch/mips/pci/fixup-tb0287.c @@ -1,7 +1,7 @@ /* * fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c index 900c6b32576c3..28962a7c66066 100644 --- a/arch/mips/pci/ops-vr41xx.c +++ b/arch/mips/pci/ops-vr41xx.c @@ -2,8 +2,8 @@ * ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series. * * Copyright (C) 2001-2003 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. */ #include <linux/pci.h> diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index d1e049b55f34f..56525711f8b75 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -2,8 +2,8 @@ * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2003 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org> * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. */ #include <linux/init.h> diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h index 8a35e32b8376f..6b1ae2eb1c065 100644 --- a/arch/mips/pci/pci-vr41xx.h +++ b/arch/mips/pci/pci-vr41xx.h @@ -2,8 +2,8 @@ * pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c index 6d9bab8905877..719f4a5b98445 100644 --- a/arch/mips/vr41xx/casio-e55/setup.c +++ b/arch/mips/vr41xx/casio-e55/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65. * - * Copyright (C) 2002-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c index d77c330a0d592..6346c59c9f9d9 100644 --- a/arch/mips/vr41xx/common/bcu.c +++ b/arch/mips/vr41xx/common/bcu.c @@ -2,8 +2,8 @@ * bcu.c, Bus Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Added support for NEC VR4133. */ #include <linux/kernel.h> diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c index ad0e8e3409d90..8ba7d04a5ec58 100644 --- a/arch/mips/vr41xx/common/cmu.c +++ b/arch/mips/vr41xx/common/cmu.c @@ -2,8 +2,8 @@ * cmu.c, Clock Mask Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copuright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Added support for NEC VR4133. */ #include <linux/init.h> diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c index 2b272f1496fe9..22cc6f2100a1a 100644 --- a/arch/mips/vr41xx/common/giu.c +++ b/arch/mips/vr41xx/common/giu.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series GIU platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 3f23d9fda6626..6d39e222b170b 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -2,8 +2,8 @@ * icu.c, Interrupt Control Unit routines for the NEC VR4100 series. * * Copyright (C) 2001-2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ */ /* * Changes: - * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> + * MontaVista Software Inc. <source@mvista.com> * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Yoichi Yuasa <yuasa@linux-mips.org> * - Coped with INTASSIGN of NEC VR4133. */ #include <linux/errno.h> diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index c64995342ba82..1386e6f081c86 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c @@ -1,7 +1,7 @@ /* * init.c, Common initialization routines for NEC VR4100 series. * - * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 9cc389109b19f..bef06872f012d 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c index 028aaf75eb216..692b4e85b7fc9 100644 --- a/arch/mips/vr41xx/common/pmu.c +++ b/arch/mips/vr41xx/common/pmu.c @@ -1,7 +1,7 @@ /* * pmu.c, Power Management Unit routines for NEC VR4100 series. * - * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c index 9f26c14edcac2..ebc5dcf0ed8e2 100644 --- a/arch/mips/vr41xx/common/rtc.c +++ b/arch/mips/vr41xx/common/rtc.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series RTC platform device. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c index 654dee6208be2..54eae56108fb9 100644 --- a/arch/mips/vr41xx/common/siu.c +++ b/arch/mips/vr41xx/common/siu.c @@ -1,7 +1,7 @@ /* * NEC VR4100 series SIU platform device. * - * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c index e0c1ac5e988e4..ff841422b6389 100644 --- a/arch/mips/vr41xx/common/type.c +++ b/arch/mips/vr41xx/common/type.c @@ -1,7 +1,7 @@ /* * type.c, System type for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c index 9eef297eca1a9..3982f378a3e60 100644 --- a/arch/mips/vr41xx/ibm-workpad/setup.c +++ b/arch/mips/vr41xx/ibm-workpad/setup.c @@ -1,7 +1,7 @@ /* * setup.c, Setup for the IBM WorkPad z50. * - * Copyright (C) 2002-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2002-2006 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 6062b62800fd2..b3ec9b10e2920 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c @@ -1,7 +1,7 @@ /* * Driver for TANBAC TB0219 base board. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ #include <asm/vr41xx/giu.h> #include <asm/vr41xx/tb0219.h> -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c index f691ffa95fbb1..b70e06133e787 100644 --- a/drivers/gpio/vr41xx_giu.c +++ b/drivers/gpio/vr41xx_giu.c @@ -2,8 +2,8 @@ * Driver for NEC VR4100 series General-purpose I/O Unit. * * Copyright (C) 2002 MontaVista Software Inc. - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> - * Copyright (C) 2003-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Author: Yoichi Yuasa <source@mvista.com> + * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ #include <asm/vr41xx/irq.h> #include <asm/vr41xx/vr41xx.h> -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265da6..d114d3a9e1e94 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -1,7 +1,7 @@ /* * Cobalt button interface driver. * - * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) return 0; } -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_DESCRIPTION("Cobalt button interface driver"); MODULE_LICENSE("GPL"); /* work with hotplug and coldplug */ diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c index ff0e8c3fbf9b7..5f1ce810815f5 100644 --- a/drivers/leds/leds-cobalt-raq.c +++ b/drivers/leds/leds-cobalt-raq.c @@ -1,7 +1,7 @@ /* * LEDs driver for the Cobalt Raq series. * - * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 659421d0ca46a..d4ad50d737b06 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -1,7 +1,7 @@ /* * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ #include "i82365.h" MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services"); -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_LICENSE("GPL"); #define CARD_MAX_SLOTS 2 diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 812f038e9bdae..9b3c15827e5c7 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c @@ -6,7 +6,7 @@ * NEC VRC4173 CARDU driver for Socket Services * (This device doesn't support CardBus. it is supporting only 16bit PC Card.) * - * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -41,7 +41,7 @@ #include "vrc4173_cardu.h" MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services"); -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_LICENSE("GPL"); static int vrc4173_cardu_slots; diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h index 7d77c74120c1c..a7d96018ed8d4 100644 --- a/drivers/pcmcia/vrc4173_cardu.h +++ b/drivers/pcmcia/vrc4173_cardu.h @@ -5,7 +5,7 @@ * BRIEF MODULE DESCRIPTION * Include file for NEC VRC4173 CARDU. * - * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index f11297aff854a..2c839d0d21bd2 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Real Time Clock unit. * - * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ #include <asm/io.h> #include <asm/uaccess.h> -MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); MODULE_DESCRIPTION("NEC VR4100 series RTC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 0573f3b5175e4..dac550e57c29c 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -1,7 +1,7 @@ /* * Driver for NEC VR4100 series Serial Interface Unit. * - * Copyright (C) 2004-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2004-2008 Yoichi Yuasa <yuasa@linux-mips.org> * * Based on drivers/serial/8250.c, by Russell King. * diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 7bad24ed04ef5..108b89e09a80d 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -1,7 +1,7 @@ /* * Cobalt server LCD frame buffer driver. * - * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -- GitLab From 01a6221a6a51ec47b9ae3ed42c396f98dd488c7e Mon Sep 17 00:00:00 2001 From: David Daney <ddaney@caviumnetworks.com> Date: Mon, 29 Jun 2009 17:18:51 -0700 Subject: [PATCH 0648/1002] MIPS: Reorganize Cavium OCTEON PCI support. Move the cavium PCI files to the arch/mips/pci directory. Also cleanup comment formatting and code layout. Code from pci-common.c, was moved into other files. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/cavium-octeon/Makefile | 4 - arch/mips/cavium-octeon/dma-octeon.c | 2 +- arch/mips/cavium-octeon/pci-common.c | 137 ---------------- .../asm/octeon/pci-octeon.h} | 30 ++-- arch/mips/pci/Makefile | 5 + .../{cavium-octeon/msi.c => pci/msi-octeon.c} | 56 +++---- .../{cavium-octeon/pci.c => pci/pci-octeon.c} | 147 +++++++++++++++--- .../pcie.c => pci/pcie-octeon.c} | 37 +++-- 8 files changed, 197 insertions(+), 221 deletions(-) delete mode 100644 arch/mips/cavium-octeon/pci-common.c rename arch/mips/{cavium-octeon/pci-common.h => include/asm/octeon/pci-octeon.h} (52%) rename arch/mips/{cavium-octeon/msi.c => pci/msi-octeon.c} (88%) rename arch/mips/{cavium-octeon/pci.c => pci/pci-octeon.c} (78%) rename arch/mips/{cavium-octeon/pcie.c => pci/pcie-octeon.c} (98%) diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 7c0528b0e34cc..d6903c3f3d513 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -14,9 +14,5 @@ obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_PCI) += pci-common.o -obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_PCI) += pcie.o -obj-$(CONFIG_PCI_MSI) += msi.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 627c162a61598..4b92bfc662db0 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c @@ -29,7 +29,7 @@ #include <dma-coherence.h> #ifdef CONFIG_PCI -#include "pci-common.h" +#include <asm/octeon/pci-octeon.h> #endif #define BAR2_PCI_ADDRESS 0x8000000000ul diff --git a/arch/mips/cavium-octeon/pci-common.c b/arch/mips/cavium-octeon/pci-common.c deleted file mode 100644 index cd029f88da7fa..0000000000000 --- a/arch/mips/cavium-octeon/pci-common.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2005-2007 Cavium Networks - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> -#include "pci-common.h" - -typeof(pcibios_map_irq) *octeon_pcibios_map_irq; -enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; - -/** - * Map a PCI device to the appropriate interrupt line - * - * @param dev The Linux PCI device structure for the device to map - * @param slot The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. - * @param pin The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. - * @return Interrupt number for the device - */ -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - if (octeon_pcibios_map_irq) - return octeon_pcibios_map_irq(dev, slot, pin); - else - panic("octeon_pcibios_map_irq doesn't point to a " - "pcibios_map_irq() function"); -} - - -/** - * Called to perform platform specific PCI setup - * - * @param dev - * @return - */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - uint16_t config; - uint32_t dconfig; - int pos; - /* - * Force the Cache line setting to 64 bytes. The standard - * Linux bus scan doesn't seem to set it. Octeon really has - * 128 byte lines, but Intel bridges get really upset if you - * try and set values above 64 bytes. Value is specified in - * 32bit words. - */ - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); - /* Set latency timers for all devices */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); - - /* Enable reporting System errors and parity errors on all devices */ - /* Enable parity checking and error reporting */ - pci_read_config_word(dev, PCI_COMMAND, &config); - config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; - pci_write_config_word(dev, PCI_COMMAND, config); - - if (dev->subordinate) { - /* Set latency timers on sub bridges */ - pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); - /* More bridge error detection */ - pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); - config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); - } - - /* Enable the PCIe normal error reporting */ - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (pos) { - /* Update Device Control */ - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); - /* Correctable Error Reporting */ - config |= PCI_EXP_DEVCTL_CERE; - /* Non-Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_NFERE; - /* Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_FERE; - /* Unsupported Request */ - config |= PCI_EXP_DEVCTL_URRE; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); - } - - /* Find the Advanced Error Reporting capability */ - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); - if (pos) { - /* Clear Uncorrectable Error Status */ - pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, - &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, - dconfig); - /* Enable reporting of all uncorrectable errors */ - /* Uncorrectable Error Mask - turned on bits disable errors */ - pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); - /* - * Leave severity at HW default. This only controls if - * errors are reported as uncorrectable or - * correctable, not if the error is reported. - */ - /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ - /* Clear Correctable Error Status */ - pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); - /* Enable reporting of all correctable errors */ - /* Correctable Error Mask - turned on bits disable errors */ - pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); - /* Advanced Error Capabilities */ - pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); - /* ECRC Generation Enable */ - if (config & PCI_ERR_CAP_ECRC_GENC) - config |= PCI_ERR_CAP_ECRC_GENE; - /* ECRC Check Enable */ - if (config & PCI_ERR_CAP_ECRC_CHKC) - config |= PCI_ERR_CAP_ECRC_CHKE; - pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); - /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ - /* Report all errors to the root complex */ - pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, - PCI_ERR_ROOT_CMD_COR_EN | - PCI_ERR_ROOT_CMD_NONFATAL_EN | - PCI_ERR_ROOT_CMD_FATAL_EN); - /* Clear the Root status register */ - pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); - pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); - } - - return 0; -} diff --git a/arch/mips/cavium-octeon/pci-common.h b/arch/mips/include/asm/octeon/pci-octeon.h similarity index 52% rename from arch/mips/cavium-octeon/pci-common.h rename to arch/mips/include/asm/octeon/pci-octeon.h index 74ae79991e456..6ac5d3e3398ea 100644 --- a/arch/mips/cavium-octeon/pci-common.h +++ b/arch/mips/include/asm/octeon/pci-octeon.h @@ -3,23 +3,29 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005-2007 Cavium Networks + * Copyright (C) 2005-2009 Cavium Networks */ -#ifndef __OCTEON_PCI_COMMON_H__ -#define __OCTEON_PCI_COMMON_H__ + +#ifndef __PCI_OCTEON_H__ +#define __PCI_OCTEON_H__ #include <linux/pci.h> /* Some PCI cards require delays when accessing config space. */ #define PCI_CONFIG_SPACE_DELAY 10000 -/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the - Octeon specific version pointed to by this variable. This function needs to - change for PCI or PCIe based hosts */ -extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq; +/* + * pcibios_map_irq() is defined inside pci-octeon.c. All it does is + * call the Octeon specific version pointed to by this variable. This + * function needs to change for PCI or PCIe based hosts. + */ +extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev, + u8 slot, u8 pin); -/* The following defines are only used when octeon_dma_bar_type = - OCTEON_DMA_BAR_TYPE_BIG */ +/* + * The following defines are used when octeon_dma_bar_type = + * OCTEON_DMA_BAR_TYPE_BIG + */ #define OCTEON_PCI_BAR1_HOLE_BITS 5 #define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3)) @@ -30,9 +36,9 @@ enum octeon_dma_bar_type { OCTEON_DMA_BAR_TYPE_PCIE }; -/** - * This is a variable to tell the DMA mapping system in dma-octeon.c - * how to map PCI DMA addresses. +/* + * This tells the DMA mapping system in dma-octeon.c how to map PCI + * DMA addresses. */ extern enum octeon_dma_bar_type octeon_dma_bar_type; diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index e8a97f59e0661..63d8a297c58da 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -52,3 +52,8 @@ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o +obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o + +ifdef CONFIG_PCI_MSI +obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o +endif diff --git a/arch/mips/cavium-octeon/msi.c b/arch/mips/pci/msi-octeon.c similarity index 88% rename from arch/mips/cavium-octeon/msi.c rename to arch/mips/pci/msi-octeon.c index 964b03b75a8f2..03742e6476571 100644 --- a/arch/mips/cavium-octeon/msi.c +++ b/arch/mips/pci/msi-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005-2007 Cavium Networks + * Copyright (C) 2005-2009 Cavium Networks */ #include <linux/kernel.h> #include <linux/init.h> @@ -16,8 +16,7 @@ #include <asm/octeon/cvmx-pci-defs.h> #include <asm/octeon/cvmx-npei-defs.h> #include <asm/octeon/cvmx-pexp-defs.h> - -#include "pci-common.h" +#include <asm/octeon/pci-octeon.h> /* * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is @@ -47,8 +46,8 @@ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock); * programming the MSI control bits [6:4] before calling * pci_enable_msi(). * - * @param dev Device requesting MSI interrupts - * @param desc MSI descriptor + * @dev: Device requesting MSI interrupts + * @desc: MSI descriptor * * Returns 0 on success. */ @@ -213,14 +212,9 @@ void arch_teardown_msi_irq(unsigned int irq) } -/** +/* * Called by the interrupt handling code when an MSI interrupt * occurs. - * - * @param cpl - * @param dev_id - * - * @return */ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) { @@ -256,31 +250,37 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id) } -/** +/* * Initializes the MSI interrupt handling code - * - * @return */ int octeon_msi_initialize(void) { - int r; if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { - r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, IRQF_SHARED, - "MSI[0:63]", octeon_msi_interrupt); + "MSI[0:63]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); } else if (octeon_is_pci_host()) { - r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, + if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt, IRQF_SHARED, - "MSI[0:15]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[16:31]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[32:47]", octeon_msi_interrupt); - r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, - IRQF_SHARED, - "MSI[48:63]", octeon_msi_interrupt); + "MSI[0:15]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[16:31]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[32:47]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed"); + + if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt, + IRQF_SHARED, + "MSI[48:63]", octeon_msi_interrupt)) + panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed"); + } return 0; } diff --git a/arch/mips/cavium-octeon/pci.c b/arch/mips/pci/pci-octeon.c similarity index 78% rename from arch/mips/cavium-octeon/pci.c rename to arch/mips/pci/pci-octeon.c index 67c0ff5e92f1a..9cb0c807f564b 100644 --- a/arch/mips/cavium-octeon/pci.c +++ b/arch/mips/pci/pci-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005-2007 Cavium Networks + * Copyright (C) 2005-2009 Cavium Networks */ #include <linux/kernel.h> #include <linux/init.h> @@ -17,8 +17,7 @@ #include <asm/octeon/octeon.h> #include <asm/octeon/cvmx-npi-defs.h> #include <asm/octeon/cvmx-pci-defs.h> - -#include "pci-common.h" +#include <asm/octeon/pci-octeon.h> #define USE_OCTEON_INTERNAL_ARBITER @@ -54,6 +53,126 @@ union octeon_pci_address { } s; }; +int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev, + u8 slot, u8 pin); +enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; + +/** + * Map a PCI device to the appropriate interrupt line + * + * @dev: The Linux PCI device structure for the device to map + * @slot: The slot number for this device on __BUS 0__. Linux + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. + * @pin: The PCI interrupt pin read from the device, then swizzled + * as it goes through each bridge. + * Returns Interrupt number for the device + */ +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + if (octeon_pcibios_map_irq) + return octeon_pcibios_map_irq(dev, slot, pin); + else + panic("octeon_pcibios_map_irq not set."); +} + + +/* + * Called to perform platform specific PCI setup + */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + uint16_t config; + uint32_t dconfig; + int pos; + /* + * Force the Cache line setting to 64 bytes. The standard + * Linux bus scan doesn't seem to set it. Octeon really has + * 128 byte lines, but Intel bridges get really upset if you + * try and set values above 64 bytes. Value is specified in + * 32bit words. + */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4); + /* Set latency timers for all devices */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48); + + /* Enable reporting System errors and parity errors on all devices */ + /* Enable parity checking and error reporting */ + pci_read_config_word(dev, PCI_COMMAND, &config); + config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + pci_write_config_word(dev, PCI_COMMAND, config); + + if (dev->subordinate) { + /* Set latency timers on sub bridges */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48); + /* More bridge error detection */ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config); + config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config); + } + + /* Enable the PCIe normal error reporting */ + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (pos) { + /* Update Device Control */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config); + /* Correctable Error Reporting */ + config |= PCI_EXP_DEVCTL_CERE; + /* Non-Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_NFERE; + /* Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_FERE; + /* Unsupported Request */ + config |= PCI_EXP_DEVCTL_URRE; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config); + } + + /* Find the Advanced Error Reporting capability */ + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + if (pos) { + /* Clear Uncorrectable Error Status */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, + &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, + dconfig); + /* Enable reporting of all uncorrectable errors */ + /* Uncorrectable Error Mask - turned on bits disable errors */ + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0); + /* + * Leave severity at HW default. This only controls if + * errors are reported as uncorrectable or + * correctable, not if the error is reported. + */ + /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */ + /* Clear Correctable Error Status */ + pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig); + /* Enable reporting of all correctable errors */ + /* Correctable Error Mask - turned on bits disable errors */ + pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0); + /* Advanced Error Capabilities */ + pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig); + /* ECRC Generation Enable */ + if (config & PCI_ERR_CAP_ECRC_GENC) + config |= PCI_ERR_CAP_ECRC_GENE; + /* ECRC Check Enable */ + if (config & PCI_ERR_CAP_ECRC_CHKC) + config |= PCI_ERR_CAP_ECRC_CHKE; + pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig); + /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */ + /* Report all errors to the root complex */ + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, + PCI_ERR_ROOT_CMD_COR_EN | + PCI_ERR_ROOT_CMD_NONFATAL_EN | + PCI_ERR_ROOT_CMD_FATAL_EN); + /* Clear the Root status register */ + pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig); + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig); + } + + return 0; +} + /** * Return the mapping of PCI device number to IRQ line. Each * character in the return string represents the interrupt @@ -136,9 +255,8 @@ int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, } -/** +/* * Read a value from configuration space - * */ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, int reg, int size, u32 *val) @@ -174,15 +292,8 @@ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn, } -/** +/* * Write a value to PCI configuration space - * - * @bus: - * @devfn: - * @reg: - * @size: - * @val: - * Returns */ static int octeon_write_config(struct pci_bus *bus, unsigned int devfn, int reg, int size, u32 val) @@ -251,10 +362,8 @@ static struct pci_controller octeon_pci_controller = { }; -/** +/* * Low level initialize the Octeon PCI controller - * - * Returns */ static void octeon_pci_initialize(void) { @@ -398,7 +507,7 @@ static void octeon_pci_initialize(void) pci_int_arb_cfg.s.en = 1; /* Internal arbiter enable */ cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64); } -#endif /* USE_OCTEON_INTERNAL_ARBITER */ +#endif /* USE_OCTEON_INTERNAL_ARBITER */ /* * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE, @@ -457,10 +566,8 @@ static void octeon_pci_initialize(void) } -/** +/* * Initialize the Octeon PCI controller - * - * Returns */ static int __init octeon_pci_setup(void) { diff --git a/arch/mips/cavium-octeon/pcie.c b/arch/mips/pci/pcie-octeon.c similarity index 98% rename from arch/mips/cavium-octeon/pcie.c rename to arch/mips/pci/pcie-octeon.c index 49d14081b3b5a..75262247f3e48 100644 --- a/arch/mips/cavium-octeon/pcie.c +++ b/arch/mips/pci/pcie-octeon.c @@ -18,8 +18,7 @@ #include <asm/octeon/cvmx-pescx-defs.h> #include <asm/octeon/cvmx-pexp-defs.h> #include <asm/octeon/cvmx-helper-errata.h> - -#include "pci-common.h" +#include <asm/octeon/pci-octeon.h> union cvmx_pcie_address { uint64_t u64; @@ -976,13 +975,13 @@ static int cvmx_pcie_rc_initialize(int pcie_port) /** * Map a PCI device to the appropriate interrupt line * - * @param dev The Linux PCI device structure for the device to map - * @param slot The slot number for this device on __BUS 0__. Linux + * @dev: The Linux PCI device structure for the device to map + * @slot: The slot number for this device on __BUS 0__. Linux * enumerates through all the bridges and figures out the * slot on Bus 0 where this device eventually hooks to. - * @param pin The PCI interrupt pin read from the device, then swizzled + * @pin: The PCI interrupt pin read from the device, then swizzled * as it goes through each bridge. - * @return Interrupt number for the device + * Returns Interrupt number for the device */ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) @@ -1025,12 +1024,12 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, /** * Read a value from configuration space * - * @param bus - * @param devfn - * @param reg - * @param size - * @param val - * @return + * @bus: + * @devfn: + * @reg: + * @size: + * @val: + * Returns */ static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus, unsigned int devfn, int reg, int size, @@ -1156,12 +1155,12 @@ static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn, /** * Write a value to PCI configuration space * - * @param bus - * @param devfn - * @param reg - * @param size - * @param val - * @return + * @bus: + * @devfn: + * @reg: + * @size: + * @val: + * Returns */ static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus, unsigned int devfn, int reg, @@ -1254,7 +1253,7 @@ static struct pci_controller octeon_pcie1_controller = { /** * Initialize the Octeon PCIe controllers * - * @return + * Returns */ static int __init octeon_pcie_setup(void) { -- GitLab From baf922780251d12bc1c24c83df60c4c278abb745 Mon Sep 17 00:00:00 2001 From: Ralf Baechle <ralf@linux-mips.org> Date: Fri, 3 Jul 2009 07:11:15 +0100 Subject: [PATCH 0649/1002] MIPS: Fix CONFIG_FLATMEM version of pfn_valid() For systems which do not define PHYS_OFFSET as 0 pfn_valid() may falsely have returned 0 on most configurations. Bug introduced by commit 752fbeb2e3555c0d236e992f1195fd7ce30e728d (linux-mips.org) rsp. 6f284a2ce7b8bc49cb8455b1763357897a899abb (kernel.org) titled "[MIPS] FLATMEM: introduce PHYS_OFFSET." Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/include/asm/page.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index dc0eaa7312816..96a14a426a7c3 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -165,7 +165,14 @@ typedef struct { unsigned long pgprot; } pgprot_t; #ifdef CONFIG_FLATMEM -#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr) +#define pfn_valid(pfn) \ +({ \ + unsigned long __pfn = (pfn); \ + /* avoid <linux/bootmem.h> include hell */ \ + extern unsigned long min_low_pfn; \ + \ + __pfn >= min_low_pfn && __pfn < max_mapnr; \ +}) #elif defined(CONFIG_SPARSEMEM) -- GitLab From 1fde902d52ee13ab9fab155bbae757fdf7daf0c1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 17:28:57 +0200 Subject: [PATCH 0650/1002] x86: atomic64: Export APIs to modules atomic64_t primitives are used by a handful of drivers, so export the APIs consistently. These were inlined before. Also mark atomic64_32.o a core object, so that the symbols are available even if not linked to core kernel pieces. Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <tip-05118ab8859492ac9ddda0154cf90e37b0a4a0b0@git.kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/Makefile | 2 +- arch/x86/lib/atomic64_32.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index c3c657c8bb834..07c31899c9c24 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,7 +10,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o ifeq ($(CONFIG_X86_32),y) - lib-y += atomic64_32.o + obj-y += atomic64_32.o lib-y += checksum_32.o lib-y += strstr_32.o lib-y += semaphore_32.o string_32.o diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index cd11803f9448f..6722a092e407e 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -1,5 +1,7 @@ #include <linux/compiler.h> +#include <linux/module.h> #include <linux/types.h> + #include <asm/processor.h> #include <asm/cmpxchg.h> #include <asm/atomic.h> @@ -21,6 +23,7 @@ u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val) { return cmpxchg8b(&ptr->counter, old_val, new_val); } +EXPORT_SYMBOL(atomic64_cmpxchg); /** * atomic64_xchg - xchg atomic64 variable @@ -41,6 +44,7 @@ u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) return old_val; } +EXPORT_SYMBOL(atomic64_xchg); /** * atomic64_set - set atomic64 variable @@ -53,6 +57,7 @@ void atomic64_set(atomic64_t *ptr, u64 new_val) { atomic64_xchg(ptr, new_val); } +EXPORT_SYMBOL(atomic64_read); /** * atomic64_read - read atomic64 variable @@ -74,6 +79,7 @@ u64 atomic64_read(atomic64_t *ptr) return res; } +EXPORT_SYMBOL(atomic64_read); /** * atomic64_add_return - add and return @@ -103,21 +109,25 @@ noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr) return new_val; } +EXPORT_SYMBOL(atomic64_add_return); u64 atomic64_sub_return(u64 delta, atomic64_t *ptr) { return atomic64_add_return(-delta, ptr); } +EXPORT_SYMBOL(atomic64_sub_return); u64 atomic64_inc_return(atomic64_t *ptr) { return atomic64_add_return(1, ptr); } +EXPORT_SYMBOL(atomic64_inc_return); u64 atomic64_dec_return(atomic64_t *ptr) { return atomic64_sub_return(1, ptr); } +EXPORT_SYMBOL(atomic64_dec_return); /** * atomic64_add - add integer to atomic64 variable @@ -130,6 +140,7 @@ void atomic64_add(u64 delta, atomic64_t *ptr) { atomic64_add_return(delta, ptr); } +EXPORT_SYMBOL(atomic64_add); /** * atomic64_sub - subtract the atomic64 variable @@ -142,6 +153,7 @@ void atomic64_sub(u64 delta, atomic64_t *ptr) { atomic64_add(-delta, ptr); } +EXPORT_SYMBOL(atomic64_sub); /** * atomic64_sub_and_test - subtract value from variable and test result @@ -158,6 +170,7 @@ int atomic64_sub_and_test(u64 delta, atomic64_t *ptr) return old_val == 0; } +EXPORT_SYMBOL(atomic64_sub_and_test); /** * atomic64_inc - increment atomic64 variable @@ -169,6 +182,7 @@ void atomic64_inc(atomic64_t *ptr) { atomic64_add(1, ptr); } +EXPORT_SYMBOL(atomic64_inc); /** * atomic64_dec - decrement atomic64 variable @@ -180,6 +194,7 @@ void atomic64_dec(atomic64_t *ptr) { atomic64_sub(1, ptr); } +EXPORT_SYMBOL(atomic64_dec); /** * atomic64_dec_and_test - decrement and test @@ -193,6 +208,7 @@ int atomic64_dec_and_test(atomic64_t *ptr) { return atomic64_sub_and_test(1, ptr); } +EXPORT_SYMBOL(atomic64_dec_and_test); /** * atomic64_inc_and_test - increment and test @@ -206,6 +222,7 @@ int atomic64_inc_and_test(atomic64_t *ptr) { return atomic64_sub_and_test(-1, ptr); } +EXPORT_SYMBOL(atomic64_inc_and_test); /** * atomic64_add_negative - add and test if negative @@ -222,3 +239,4 @@ int atomic64_add_negative(u64 delta, atomic64_t *ptr) return old_val < 0; } +EXPORT_SYMBOL(atomic64_add_negative); -- GitLab From 3a8d1788b37435baf6c296f4ea8beb4fa4955f44 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 19:56:36 +0200 Subject: [PATCH 0651/1002] x86: atomic64: Improve atomic64_xchg() Remove the read-first logic from atomic64_xchg() and simplify the loop. This function was the last user of __atomic64_read() - remove it. Also, change the 'real_val' assumption from the somewhat quirky 1ULL << 32 value to the (just as arbitrary, but simpler) value of 0. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <tip-05118ab8859492ac9ddda0154cf90e37b0a4a0b0@git.kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 9 --------- arch/x86/lib/atomic64_32.c | 21 +++++++++++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index aa045deb2e757..d7c8849b8c674 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -268,15 +268,6 @@ typedef struct { #define ATOMIC64_INIT(val) { (val) } -/** - * atomic64_read - read atomic64 variable - * @ptr: pointer of type atomic64_t - * - * Atomically reads the value of @v. - * Doesn't imply a read memory barrier. - */ -#define __atomic64_read(ptr) ((ptr)->counter) - extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); /** diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index 6722a092e407e..a804f96e90e2f 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -33,14 +33,23 @@ EXPORT_SYMBOL(atomic64_cmpxchg); * Atomically xchgs the value of @ptr to @new_val and returns * the old value. */ - u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) { - u64 old_val; + /* + * Try first with a (possibly incorrect) assumption about + * what we have there. We'll do two loops most likely, + * but we'll get an ownership MESI transaction straight away + * instead of a read transaction followed by a + * flush-for-ownership transaction: + */ + u64 old_val, real_val = 0; do { - old_val = __atomic64_read(ptr); - } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val); + old_val = real_val; + + real_val = atomic64_cmpxchg(ptr, old_val, new_val); + + } while (real_val != old_val); return old_val; } @@ -91,13 +100,13 @@ EXPORT_SYMBOL(atomic64_read); noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr) { /* - * Try first with a (probably incorrect) assumption about + * Try first with a (possibly incorrect) assumption about * what we have there. We'll do two loops most likely, * but we'll get an ownership MESI transaction straight away * instead of a read transaction followed by a * flush-for-ownership transaction: */ - u64 old_val, new_val, real_val = 1ULL << 32; + u64 old_val, new_val, real_val = 0; do { old_val = real_val; -- GitLab From b59e64d0ddb756af57ea032383bfd393a286a8e8 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <hare@suse.de> Date: Thu, 2 Jul 2009 22:02:06 +0200 Subject: [PATCH 0652/1002] cciss: Ignore stale commands after reboot When doing an unexpected shutdown like kexec the cciss firmware might still have some commands in flight, which it is trying to complete. The driver is doing it's best on resetting the HBA, but sadly there's a firmware issue causing the firmware _not_ to abort or drop old commands. So the firmware will send us commands which we haven't accounted for, causing the driver to panic. With this patch we're just ignoring these commands as there is nothing we could be doing with them anyway. Signed-off-by: Hannes Reinecke <hare@suse.de> Acked-by: Mike Miller <mike.miller@hp.com> Signed-off-by: Jens Axboe <axboe@carl.(none)> --- drivers/block/cciss.c | 15 +++++++++++++-- drivers/block/cciss_cmd.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c7a527c08a098..65a0655e7fc84 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -226,8 +226,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c) static inline void removeQ(CommandList_struct *c) { - if (WARN_ON(hlist_unhashed(&c->list))) + /* + * After kexec/dump some commands might still + * be in flight, which the firmware will try + * to complete. Resetting the firmware doesn't work + * with old fw revisions, so we have to mark + * them off as 'stale' to prevent the driver from + * falling over. + */ + if (WARN_ON(hlist_unhashed(&c->list))) { + c->cmd_type = CMD_MSG_STALE; return; + } hlist_del_init(&c->list); } @@ -4246,7 +4256,8 @@ static void fail_all_cmds(unsigned long ctlr) while (!hlist_empty(&h->cmpQ)) { c = hlist_entry(h->cmpQ.first, CommandList_struct, list); removeQ(c); - c->err_info->CommandStatus = CMD_HARDWARE_ERR; + if (c->cmd_type != CMD_MSG_STALE) + c->err_info->CommandStatus = CMD_HARDWARE_ERR; if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); } else if (c->cmd_type == CMD_IOCTL_PEND) diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd665b00c7c5b..dbaed1ea0da3c 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct { #define CMD_SCSI 0x03 #define CMD_MSG_DONE 0x04 #define CMD_MSG_TIMEOUT 0x05 +#define CMD_MSG_STALE 0xff /* This structure needs to be divisible by 8 for new * indexing method. -- GitLab From ab0fd1debe730ec9998678a0c53caefbd121ed10 Mon Sep 17 00:00:00 2001 From: Tejun Heo <tj@kernel.org> Date: Fri, 3 Jul 2009 12:56:18 +0200 Subject: [PATCH 0653/1002] block: don't merge requests of different failfast settings Block layer used to merge requests and bios with different failfast settings. This caused regular IOs to fail prematurely when they were merged into failfast requests for readahead. Niel Lambrechts could trigger the problem semi-reliably on ext4 when resuming from STR. ext4 uses readahead when reading inodes and combined with the deterministic extra SATA PHY exception cycle during resume on the specific configuration, non-readahead inode read would fail causing ext4 errors. Please read the following thread for details. http://lkml.org/lkml/2009/5/23/21 This patch makes block layer reject merging if the failfast settings don't match. This is correct but likely to lower IO performance by preventing regular IOs from mingling into surrounding readahead requests. Changes to allow such mixed merges and handle errors correctly will be added later. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Niel Lambrechts <niel.lambrechts@gmail.com> Cc: Theodore Tso <tytso@mit.edu> Signed-off-by: Jens Axboe <axboe@carl.(none)> --- block/blk-merge.c | 6 ++++++ block/elevator.c | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/block/blk-merge.c b/block/blk-merge.c index 39ce64432ba6d..e1999679a4d51 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -350,6 +350,12 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (blk_integrity_rq(req) != blk_integrity_rq(next)) return 0; + /* don't merge requests of different failfast settings */ + if (blk_failfast_dev(req) != blk_failfast_dev(next) || + blk_failfast_transport(req) != blk_failfast_transport(next) || + blk_failfast_driver(req) != blk_failfast_driver(next)) + return 0; + /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn diff --git a/block/elevator.c b/block/elevator.c index ca861927ba41b..6f2375339a996 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -100,6 +100,14 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio) if (bio_integrity(bio) != blk_integrity_rq(rq)) return 0; + /* + * Don't merge if failfast settings don't match + */ + if (bio_failfast_dev(bio) != blk_failfast_dev(rq) || + bio_failfast_transport(bio) != blk_failfast_transport(rq) || + bio_failfast_driver(bio) != blk_failfast_driver(rq)) + return 0; + if (!elv_iosched_allow_merge(rq, bio)) return 0; -- GitLab From ddf9a003d32f720805ac30bcc15755e9289073de Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 3 Jul 2009 20:11:30 +0200 Subject: [PATCH 0654/1002] x86: atomic64: Clean up atomic64_sub_and_test() and atomic64_add_negative() Linus noticed that the variable name 'old_val' is confusingly named in these functions - the correct naming is 'new_val'. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <alpine.LFD.2.01.0907030942260.3210@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/lib/atomic64_32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index a804f96e90e2f..1d98c9eb6eacb 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -175,9 +175,9 @@ EXPORT_SYMBOL(atomic64_sub); */ int atomic64_sub_and_test(u64 delta, atomic64_t *ptr) { - u64 old_val = atomic64_sub_return(delta, ptr); + u64 new_val = atomic64_sub_return(delta, ptr); - return old_val == 0; + return new_val == 0; } EXPORT_SYMBOL(atomic64_sub_and_test); @@ -244,8 +244,8 @@ EXPORT_SYMBOL(atomic64_inc_and_test); */ int atomic64_add_negative(u64 delta, atomic64_t *ptr) { - long long old_val = atomic64_add_return(delta, ptr); + s64 new_val = atomic64_add_return(delta, ptr); - return old_val < 0; + return new_val < 0; } EXPORT_SYMBOL(atomic64_add_negative); -- GitLab From 022b466fc353d3dc7a152451144be656248666ce Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Fri, 3 Jul 2009 23:03:30 +0200 Subject: [PATCH 0655/1002] ALSA: hda - Avoid invalid formats and rates with shared SPDIF Check whether formats and rates don't result in zero due to the restriction of SPDIF sharing. If any of them can be zero, disable the SPDIF sharing mode instead. Otherwise it will lead to a PCM configuration error. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_codec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 462e2cedaa6af..26d255de6bebb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3470,10 +3470,16 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, } mutex_lock(&codec->spdif_mutex); if (mout->share_spdif) { - runtime->hw.rates &= mout->spdif_rates; - runtime->hw.formats &= mout->spdif_formats; - if (mout->spdif_maxbps < hinfo->maxbps) - hinfo->maxbps = mout->spdif_maxbps; + if ((runtime->hw.rates & mout->spdif_rates) && + (runtime->hw.formats & mout->spdif_formats)) { + runtime->hw.rates &= mout->spdif_rates; + runtime->hw.formats &= mout->spdif_formats; + if (mout->spdif_maxbps < hinfo->maxbps) + hinfo->maxbps = mout->spdif_maxbps; + } else { + mout->share_spdif = 0; + /* FIXME: need notify? */ + } } mutex_unlock(&codec->spdif_mutex); } -- GitLab From 70d321e6380f128096429d6e5b678f94ab0cef5d Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Fri, 3 Jul 2009 23:06:45 +0200 Subject: [PATCH 0656/1002] ALSA: hda - Call snd_pcm_lib_hw_rates() again after codec open callback The PCM rates bit field may have been changed by the codec open callback. In that case, we need to reset rate_min and rate_max. So, simply call snd_pcm_lib_hw_rates() again after the codec open callback. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4e9ea70802701..b36dc46615a4e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1454,6 +1454,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&chip->open_mutex); return err; } + snd_pcm_limit_hw_rates(runtime); spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = substream; azx_dev->running = 0; -- GitLab From c470331e69bd54d11a9ea3c27a0e4ad783d02d6b Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Fri, 3 Jul 2009 23:10:23 +0200 Subject: [PATCH 0657/1002] ALSA: hda - Add sanity check in PCM open callback Add some sanity checks of struct snd_pcm_hardware fields in the PCM open callback of hda driver. This makes a bit easier to debug any PCM setup errors in the codec side. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_intel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b36dc46615a4e..1877d95d4aa67 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1464,6 +1464,12 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); + if (snd_BUG_ON(!runtime->hw.channels_min || !runtime->hw.channels_max)) + return -EINVAL; + if (snd_BUG_ON(!runtime->hw.formats)) + return -EINVAL; + if (snd_BUG_ON(!runtime->hw.rates)) + return -EINVAL; return 0; } -- GitLab From 954a973cab37ad5df3f87f08964166abd956cc17 Mon Sep 17 00:00:00 2001 From: Kay Sievers <kay.sievers@suse.de> Date: Fri, 3 Jul 2009 20:56:05 +0200 Subject: [PATCH 0658/1002] sound: do not set DEVNAME for OSS devices Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/sound_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/sound_core.c b/sound/sound_core.c index 12522e6913d92..a41f8b127f49c 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -10,6 +10,8 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/kdev_t.h> +#include <linux/major.h> #include <sound/core.h> #ifdef CONFIG_SOUND_OSS_CORE @@ -29,6 +31,8 @@ MODULE_LICENSE("GPL"); static char *sound_nodename(struct device *dev) { + if (MAJOR(dev->devt) == SOUND_MAJOR) + return NULL; return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev)); } @@ -104,7 +108,6 @@ module_exit(cleanup_soundcore); #include <linux/types.h> #include <linux/kernel.h> #include <linux/sound.h> -#include <linux/major.h> #include <linux/kmod.h> #define SOUND_STEP 16 -- GitLab From c615c9f3f3cea60279b1bb38e8ef27bd575ecd0c Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Thu, 2 Jul 2009 16:57:23 +0000 Subject: [PATCH 0659/1002] xfrm4: fix the ports decode of sctp protocol The SCTP pushed the skb data above the sctp chunk header, so the check of pskb_may_pull(skb, xprth + 4 - skb->data) in _decode_session4() will never return 0 because xprth + 4 - skb->data < 0, the ports decode of sctp will always fail. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/xfrm4_policy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 60d918c96a4ff..0071ee6f441f1 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -136,7 +136,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: - if (pskb_may_pull(skb, xprth + 4 - skb->data)) { + if (xprth + 4 < skb->data || + pskb_may_pull(skb, xprth + 4 - skb->data)) { __be16 *ports = (__be16 *)xprth; fl->fl_ip_sport = ports[!!reverse]; -- GitLab From 59cae0092e4da753b5a2adb32933e0d1b223bcc5 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Thu, 2 Jul 2009 16:59:49 +0000 Subject: [PATCH 0660/1002] xfrm6: fix the proto and ports decode of sctp protocol The SCTP pushed the skb above the sctp chunk header, so the check of pskb_may_pull(skb, nh + offset + 1 - skb->data) in _decode_session6() will never return 0 and the ports decode of sctp will always fail. (nh + offset + 1 - skb->data < 0) Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv6/xfrm6_policy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b4b16a43f2771..3a3c677bc0f25 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); - while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { + while (nh + offset + 1 < skb->data || + pskb_may_pull(skb, nh + offset + 1 - skb->data)) { nh = skb_network_header(skb); exthdr = (struct ipv6_opt_hdr *)(nh + offset); @@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) case IPPROTO_TCP: case IPPROTO_SCTP: case IPPROTO_DCCP: - if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { + if (!onlyproto && (nh + offset + 4 < skb->data || + pskb_may_pull(skb, nh + offset + 4 - skb->data))) { __be16 *ports = (__be16 *)exthdr; fl->fl_ip_sport = ports[!!reverse]; -- GitLab From a1ed05263b74921742b454ef52c30b609ec6940f Mon Sep 17 00:00:00 2001 From: Brian Haley <brian.haley@hp.com> Date: Thu, 2 Jul 2009 07:10:52 +0000 Subject: [PATCH 0661/1002] IPv6: preferred lifetime of address not getting updated There's a bug in addrconf_prefix_rcv() where it won't update the preferred lifetime of an IPv6 address if the current valid lifetime of the address is less than 2 hours (the minimum value in the RA). For example, If I send a router advertisement with a prefix that has valid lifetime = preferred lifetime = 2 hours we'll build this address: 3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:217:8ff:fe7d:4718/64 scope global dynamic valid_lft 7175sec preferred_lft 7175sec If I then send the same prefix with valid lifetime = preferred lifetime = 0 it will be ignored since the minimum valid lifetime is 2 hours: 3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:217:8ff:fe7d:4718/64 scope global dynamic valid_lft 7161sec preferred_lft 7161sec But according to RFC 4862 we should always reset the preferred lifetime even if the valid lifetime is invalid, which would cause the address to immediately get deprecated. So with this patch we'd see this: 5: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000 inet6 2001:1890:1109:a20:21f:29ff:fe5a:ef04/64 scope global deprecated dynamic valid_lft 7163sec preferred_lft 0sec The comment winds-up being 5x the size of the code to fix the problem. Update the preferred lifetime of IPv6 addresses derived from a prefix info option in a router advertisement even if the valid lifetime in the option is invalid, as specified in RFC 4862 Section 5.5.3e. Fixes an issue where an address will not immediately become deprecated. Reported by Jens Rosenboom. Signed-off-by: Brian Haley <brian.haley@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv6/addrconf.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3883b4036a74c..43b3c9f89c12c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1916,8 +1916,32 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) update_lft = 1; else if (stored_lft <= MIN_VALID_LIFETIME) { /* valid_lft <= stored_lft is always true */ - /* XXX: IPsec */ - update_lft = 0; + /* + * RFC 4862 Section 5.5.3e: + * "Note that the preferred lifetime of + * the corresponding address is always + * reset to the Preferred Lifetime in + * the received Prefix Information + * option, regardless of whether the + * valid lifetime is also reset or + * ignored." + * + * So if the preferred lifetime in + * this advertisement is different + * than what we have stored, but the + * valid lifetime is invalid, just + * reset prefered_lft. + * + * We must set the valid lifetime + * to the stored lifetime since we'll + * be updating the timestamp below, + * else we'll set it back to the + * minumum. + */ + if (prefered_lft != ifp->prefered_lft) { + valid_lft = stored_lft; + update_lft = 1; + } } else { valid_lft = MIN_VALID_LIFETIME; if (valid_lft < prefered_lft) @@ -3085,7 +3109,7 @@ static void addrconf_verify(unsigned long foo) spin_unlock(&ifp->lock); continue; } else if (age >= ifp->prefered_lft) { - /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ + /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */ int deprecate = 0; if (!(ifp->flags&IFA_F_DEPRECATED)) { -- GitLab From 4322c5bee85ed58042ec04235ec7086065ad5074 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:06 +0000 Subject: [PATCH 0662/1002] qlge: Expand coverage of hw lock for config register. The hardware semaphore covers the configuration register as well as the ICB registers. The ICB high and low regs contain the address of the initialization control block and the config register is used to signal the hardware that a block is ready to be downloaded. Currently we were only protecting the ICB regs. This changes expands to cover the config register as well. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 90d1f76c0e8b0..7f372672ac4ef 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -214,6 +214,10 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, return -ENOMEM; } + status = ql_sem_spinlock(qdev, SEM_ICB_MASK); + if (status) + return status; + status = ql_wait_cfg(qdev, bit); if (status) { QPRINTK(qdev, IFUP, ERR, @@ -221,12 +225,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, goto exit; } - status = ql_sem_spinlock(qdev, SEM_ICB_MASK); - if (status) - goto exit; ql_write32(qdev, ICB_L, (u32) map); ql_write32(qdev, ICB_H, (u32) (map >> 32)); - ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ mask = CFG_Q_MASK | (bit << 16); value = bit | (q_id << CFG_Q_SHIFT); @@ -237,6 +237,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, */ status = ql_wait_cfg(qdev, bit); exit: + ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */ pci_unmap_single(qdev->pdev, map, size, direction); return status; } -- GitLab From a5f59dc926844bf95be2261c1bb0a24597b7a8c5 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:07 +0000 Subject: [PATCH 0663/1002] qlge: Clear frame to queue routing before reset. Not clearing the routing bits can cause frames to erroneously get routed to management processor. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 41 ++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 7f372672ac4ef..1da831e994222 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3040,25 +3040,40 @@ static int ql_start_rss(struct ql_adapter *qdev) return status; } -/* Initialize the frame-to-queue routing. */ -static int ql_route_initialize(struct ql_adapter *qdev) +static int ql_clear_routing_entries(struct ql_adapter *qdev) { - int status = 0; - int i; + int i, status = 0; status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); if (status) return status; - /* Clear all the entries in the routing table. */ for (i = 0; i < 16; i++) { status = ql_set_routing_reg(qdev, i, 0, 0); if (status) { QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for CAM packets.\n"); - goto exit; + "Failed to init routing register for CAM " + "packets.\n"); + break; } } + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); + return status; +} + +/* Initialize the frame-to-queue routing. */ +static int ql_route_initialize(struct ql_adapter *qdev) +{ + int status = 0; + + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return status; + + /* Clear all the entries in the routing table. */ + status = ql_clear_routing_entries(qdev); + if (status) + goto exit; status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); if (status) { @@ -3211,9 +3226,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev) { u32 value; int status = 0; - unsigned long end_jiffies = jiffies + - max((unsigned long)1, usecs_to_jiffies(30)); + unsigned long end_jiffies; + /* Clear all the entries in the routing table. */ + status = ql_clear_routing_entries(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n"); + return status; + } + + end_jiffies = jiffies + + max((unsigned long)1, usecs_to_jiffies(30)); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); do { -- GitLab From 8b007de19026e91991ae70ca0def31c42435e008 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:08 +0000 Subject: [PATCH 0664/1002] qlge: Fix carrier on condition. We were turning on the carrier without verifying the link was up. This adds link up to the link initialize check before turning carrier on. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 1da831e994222..c226257dc432d 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3343,7 +3343,11 @@ static int ql_adapter_up(struct ql_adapter *qdev) } set_bit(QL_ADAPTER_UP, &qdev->flags); ql_alloc_rx_buffers(qdev); - if ((ql_read32(qdev, STS) & qdev->port_init)) + /* If the port is initialized and the + * link is up the turn on the carrier. + */ + if ((ql_read32(qdev, STS) & qdev->port_init) && + (ql_read32(qdev, STS) & qdev->port_link_up)) netif_carrier_on(qdev->ndev); ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); -- GitLab From 6e9e4795e688fd61fa83f7f4cad4992939fd4ca3 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:09 +0000 Subject: [PATCH 0665/1002] qlge: Fix redundant call to free resources. The caller will free acquired resouces if a failure occurs. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c226257dc432d..1b75f6efd7f49 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3374,11 +3374,6 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev) return -ENOMEM; } status = ql_request_irq(qdev); - if (status) - goto err_irq; - return status; -err_irq: - ql_free_mem_resources(qdev); return status; } -- GitLab From 13cfd5be53d01a9316907512f17f34d3858450e8 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:10 +0000 Subject: [PATCH 0666/1002] qlge: Fix tx byte counter. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 1b75f6efd7f49..74ed84a288c25 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1629,7 +1629,7 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; tx_ring_desc = &tx_ring->q[mac_rsp->tid]; ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); - qdev->stats.tx_bytes += tx_ring_desc->map_cnt; + qdev->stats.tx_bytes += (tx_ring_desc->skb)->len; qdev->stats.tx_packets++; dev_kfree_skb(tx_ring_desc->skb); tx_ring_desc->skb = NULL; -- GitLab From 7fab3bfe08a2c5c4221685499ec4fef83ad82f83 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:11 +0000 Subject: [PATCH 0667/1002] qlge: Fix MAC address bonding issue. This addes functionality to set/clear the MAC address in the hardware when the link goes up/down. The MAC address register is persistent across function resets. In bonding the same address can bounce from one port to the other. This can cause packets to be delivered to the wrong port. This patch clears the MAC address in the hardware when the link is down and sets it when the link comes up. It was found that pulling/pushing the cable from one port to another causes the same MAC address to be in both ports. The next patch in this series will use this functionality as well. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_main.c | 50 +++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 74ed84a288c25..46dea2bd94d03 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -413,6 +413,41 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, return status; } +/* Set or clear MAC address in hardware. We sometimes + * have to clear it to prevent wrong frame routing + * especially in a bonding environment. + */ +static int ql_set_mac_addr(struct ql_adapter *qdev, int set) +{ + int status; + char zero_mac_addr[ETH_ALEN]; + char *addr; + + if (set) { + addr = &qdev->ndev->dev_addr[0]; + QPRINTK(qdev, IFUP, DEBUG, + "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5]); + } else { + memset(zero_mac_addr, 0, ETH_ALEN); + addr = &zero_mac_addr[0]; + QPRINTK(qdev, IFUP, DEBUG, + "Clearing MAC address on %s\n", + qdev->ndev->name); + } + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; + status = ql_set_mac_addr_reg(qdev, (u8 *) addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + QPRINTK(qdev, IFUP, ERR, "Failed to init mac " + "address.\n"); + return status; +} + /* Get a specific frame routing value from the CAM. * Used for debug and reg dump. */ @@ -3112,14 +3147,15 @@ static int ql_route_initialize(struct ql_adapter *qdev) int ql_cam_route_initialize(struct ql_adapter *qdev) { - int status; + int status, set; - status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); - if (status) - return status; - status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); - ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + /* If check if the link is up and use to + * determine if we are setting or clearing + * the MAC address in the CAM. + */ + set = ql_read32(qdev, STS); + set &= qdev->port_link_up; + status = ql_set_mac_addr(qdev, set); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); return status; -- GitLab From 6a47330892e697ae27d2d56a3c4c7fec2015be93 Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:12 +0000 Subject: [PATCH 0668/1002] qlge: Add/use function for link up/down. We need to set/clear the mac address register when the link goes up/down respectively. Without this both ports of a 2-port device can end up with the same mac address in a bonding scenario. The new ql_link_on() and ql_link_off() will also be used in handling certain firmware events. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge.h | 2 ++ drivers/net/qlge/qlge_main.c | 26 +++++++++++++++++++++----- drivers/net/qlge/qlge_mpi.c | 6 +++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 156e02e8905dd..6ed5317ab1c09 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1607,6 +1607,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_mb_about_fw(struct ql_adapter *qdev); +void ql_link_on(struct ql_adapter *qdev); +void ql_link_off(struct ql_adapter *qdev); #if 1 #define QL_ALL_DUMP diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 46dea2bd94d03..35ba95a9b5db3 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -448,6 +448,22 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) return status; } +void ql_link_on(struct ql_adapter *qdev) +{ + QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n", + qdev->ndev->name); + netif_carrier_on(qdev->ndev); + ql_set_mac_addr(qdev, 1); +} + +void ql_link_off(struct ql_adapter *qdev) +{ + QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n", + qdev->ndev->name); + netif_carrier_off(qdev->ndev); + ql_set_mac_addr(qdev, 0); +} + /* Get a specific frame routing value from the CAM. * Used for debug and reg dump. */ @@ -1696,13 +1712,13 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, /* Fire up a handler to reset the MPI processor. */ void ql_queue_fw_error(struct ql_adapter *qdev) { - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); } void ql_queue_asic_error(struct ql_adapter *qdev) { - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); ql_disable_interrupts(qdev); /* Clear adapter up bit to signal the recovery * process that it shouldn't kill the reset worker @@ -3312,7 +3328,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) int i, status = 0; struct rx_ring *rx_ring; - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); /* Don't kill the reset worker thread if we * are in the process of recovery. @@ -3384,7 +3400,7 @@ static int ql_adapter_up(struct ql_adapter *qdev) */ if ((ql_read32(qdev, STS) & qdev->port_init) && (ql_read32(qdev, STS) & qdev->port_link_up)) - netif_carrier_on(qdev->ndev); + ql_link_on(qdev); ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); netif_tx_start_all_queues(qdev->ndev); @@ -4035,7 +4051,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, pci_disable_device(pdev); return err; } - netif_carrier_off(ndev); + ql_link_off(qdev); ql_display_dev_info(ndev); cards_found++; return 0; diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 71afbf8b9c50c..6685bd97da91f 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -238,7 +238,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) &qdev->mpi_port_cfg_work, 0); } - netif_carrier_on(qdev->ndev); + ql_link_on(qdev); } static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) @@ -251,7 +251,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) if (status) QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); } static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) @@ -849,7 +849,7 @@ void ql_mpi_idc_work(struct work_struct *work) case MB_CMD_PORT_RESET: case MB_CMD_SET_PORT_CFG: case MB_CMD_STOP_FW: - netif_carrier_off(qdev->ndev); + ql_link_off(qdev); /* Signal the resulting link up AEN * that the frame routing and mac addr * needs to be set. -- GitLab From e332471c035708441de89d4c59f7f7cdc2700c0d Mon Sep 17 00:00:00 2001 From: Ron Mercer <ron.mercer@qlogic.com> Date: Thu, 2 Jul 2009 06:06:13 +0000 Subject: [PATCH 0669/1002] qlge: Fix sizeof usage. Some usage was only sizing a pointer rather than the data type. Signed-off-by: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/qlge/qlge_ethtool.c | 4 ++-- drivers/net/qlge/qlge_main.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 37c99fe79770f..eb6a9ee640ed9 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -59,7 +59,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cqicb->pkt_delay = cpu_to_le16(qdev->tx_max_coalesced_frames); cqicb->flags = FLAGS_LI; - status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { QPRINTK(qdev, IFUP, ERR, @@ -82,7 +82,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames); cqicb->flags = FLAGS_LI; - status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), + status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { QPRINTK(qdev, IFUP, ERR, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 35ba95a9b5db3..5768af17f168b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2156,7 +2156,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) } tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; mac_iocb_ptr = tx_ring_desc->queue_entry; - memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr)); + memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr)); mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; mac_iocb_ptr->tid = tx_ring_desc->index; @@ -2795,7 +2795,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) ql_init_tx_ring(qdev, tx_ring); - err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ, + err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ, (u16) tx_ring->wq_id); if (err) { QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); @@ -3060,7 +3060,7 @@ static int ql_start_rss(struct ql_adapter *qdev) int i; u8 *hash_id = (u8 *) ricb->hash_cq_id; - memset((void *)ricb, 0, sizeof(ricb)); + memset((void *)ricb, 0, sizeof(*ricb)); ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; ricb->flags = @@ -3082,7 +3082,7 @@ static int ql_start_rss(struct ql_adapter *qdev) QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); - status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); + status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); return status; @@ -3489,7 +3489,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; - memset((void *)tx_ring, 0, sizeof(tx_ring)); + memset((void *)tx_ring, 0, sizeof(*tx_ring)); tx_ring->qdev = qdev; tx_ring->wq_id = i; tx_ring->wq_len = qdev->tx_ring_size; @@ -3505,7 +3505,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) for (i = 0; i < qdev->rx_ring_count; i++) { rx_ring = &qdev->rx_ring[i]; - memset((void *)rx_ring, 0, sizeof(rx_ring)); + memset((void *)rx_ring, 0, sizeof(*rx_ring)); rx_ring->qdev = qdev; rx_ring->cq_id = i; rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ @@ -3864,7 +3864,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, int pos, err = 0; u16 val16; - memset((void *)qdev, 0, sizeof(qdev)); + memset((void *)qdev, 0, sizeof(*qdev)); err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "PCI device enable failed.\n"); -- GitLab From 63d6e1d80a8c3118be2ca0f1f21ba883f282060c Mon Sep 17 00:00:00 2001 From: Don Skidmore <donald.c.skidmore@intel.com> Date: Thu, 2 Jul 2009 12:50:12 +0000 Subject: [PATCH 0670/1002] ixgbe: fix issues with failing to detect insert of unsupported module Several small fixes around negative test case of the insertion of a IXGBE_ERR_NOT_SUPPORTED module. - mdio45_probe call was always failing due to mdio.prtad not being set. The function set to mdio.mdio_read was still working as we just happen to always be at prtad == 0. This will allow us to set the phy_id and phy.type correctly now. - There was timing issue with i2c calls when initiated from a tasklet. A small delay was added to allow the electrical oscillation to calm down. - Logic change in ixgbe_sfp_task that allows NOT_SUPPORTED condition to be recognized. Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 8 ++++++-- drivers/net/ixgbe/ixgbe_phy.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 5588ef493a3d9..aaf482c0d520d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3724,7 +3724,7 @@ static void ixgbe_sfp_task(struct work_struct *work) if ((hw->phy.type == ixgbe_phy_nl) && (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { s32 ret = hw->phy.ops.identify_sfp(hw); - if (ret) + if (ret == IXGBE_ERR_SFP_NOT_PRESENT) goto reschedule; ret = hw->phy.ops.reset(hw); if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { @@ -4534,13 +4534,17 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work) u32 err; adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; + + /* Time for electrical oscillations to settle down */ + msleep(100); err = hw->phy.ops.identify_sfp(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { dev_err(&adapter->pdev->dev, "failed to initialize because " "an unsupported SFP+ module type was detected.\n" "Reload the driver after installing a supported " "module.\n"); - ixgbe_down(adapter); + unregister_netdev(adapter->netdev); return; } hw->mac.ops.setup_sfp(hw); diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 453e966762f0e..9ecad17522c33 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -60,6 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { + hw->phy.mdio.prtad = phy_addr; if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { ixgbe_get_phy_id(hw); hw->phy.type = @@ -68,6 +69,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) break; } } + /* clear value if nothing found */ + hw->phy.mdio.prtad = 0; } else { status = 0; } -- GitLab From 19343de279d28e4ed039c8ad00510d19dc4d6d12 Mon Sep 17 00:00:00 2001 From: Don Skidmore <donald.c.skidmore@intel.com> Date: Thu, 2 Jul 2009 12:50:31 +0000 Subject: [PATCH 0671/1002] ixgbe: fix regression on some 82598 adapters The change to check the SFP+ module again on open() was causing the XFP (non-SFP+) adapters to be rejected. We only want to try and re-identify the SFP+ module if the original probe found that this device was an SFP+ device. So for this code path (driver loaded with SFP module, module inserted, ifconfig up of the device) the type will be ixgbe_phy_unknown for an unidentified SFP+ module. So we only check if that is the case. This problem also shows up on Copper devices. Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index aaf482c0d520d..cf39f5a470374 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2697,19 +2697,23 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* * For hot-pluggable SFP+ devices, a new SFP+ module may have - * arrived before interrupts were enabled. We need to kick off - * the SFP+ module setup first, then try to bring up link. + * arrived before interrupts were enabled but after probe. Such + * devices wouldn't have their type identified yet. We need to + * kick off the SFP+ module setup first, then try to bring up link. * If we're not hot-pluggable SFP+, we just need to configure link * and bring it up. */ - err = hw->phy.ops.identify(hw); - if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize because " - "an unsupported SFP+ module type was detected.\n" - "Reload the driver after installing a supported " - "module.\n"); - ixgbe_down(adapter); - return err; + if (hw->phy.type == ixgbe_phy_unknown) { + err = hw->phy.ops.identify(hw); + if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { + dev_err(&adapter->pdev->dev, "failed to initialize " + "because an unsupported SFP+ module type " + "was detected.\n" + "Reload the driver after installing a " + "supported module.\n"); + ixgbe_down(adapter); + return err; + } } if (ixgbe_is_sfp(hw)) { -- GitLab From 5da43c1a78cbc16518017dfb058da6ec4829781b Mon Sep 17 00:00:00 2001 From: Don Skidmore <donald.c.skidmore@intel.com> Date: Thu, 2 Jul 2009 12:50:52 +0000 Subject: [PATCH 0672/1002] ixgbe: fix inconsistent SFP/SFP+ failure results. Currently if we loaded the driver, insert an unsupported module, and then attempt to "ifconfig up" the device it will be brought down but the netdev would not be unregistered. This behavior is different than all other code paths. This patch corrects that by down'ing the device and then scheduling the sfp_config_module_task tasklet. The tasklet will detect this condition (like it does with other code paths) and do the unregister_netdev(). I also removed the log message as this condition (an unsupported SFP+ module) will be logged in sfp_config_module_task. Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cf39f5a470374..a3061aacffd84 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2706,12 +2706,12 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) if (hw->phy.type == ixgbe_phy_unknown) { err = hw->phy.ops.identify(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { - dev_err(&adapter->pdev->dev, "failed to initialize " - "because an unsupported SFP+ module type " - "was detected.\n" - "Reload the driver after installing a " - "supported module.\n"); + /* + * Take the device down and schedule the sfp tasklet + * which will unregister_netdev and log it. + */ ixgbe_down(adapter); + schedule_work(&adapter->sfp_config_module_task); return err; } } -- GitLab From e5d57af52464f37dd3c67906a493a6400bc51b43 Mon Sep 17 00:00:00 2001 From: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Date: Thu, 2 Jul 2009 12:51:10 +0000 Subject: [PATCH 0673/1002] ixgbe: Not allow 8259x unsupported wol options change from ethtool Wake-on-lan is currently only supported by 82599 KX4 devices, in all other cases return a proper value from ixgbe_wol_exclusion function call. Otherwise from ethtool we will be able to change wol options of unsupported 8259x devices. Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_ethtool.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0f7b6a3a2e682..2a978008fd6ef 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1830,7 +1830,6 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, break; default: wol->supported = 0; - retval = 0; } return retval; -- GitLab From e65fa87c225fadd1980068b7d360e08ac0e985dd Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:27:31 +0000 Subject: [PATCH 0674/1002] e1000e: PHY loopback broken on 82578 PHY loopback on 82578 fails to work as a result of flushing the packets in the FIFO buffer in the link stall workaround. Don't perform the workaround if in PHY loopback mode. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/defines.h | 2 ++ drivers/net/e1000e/phy.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 8890c97e11204..4329ec34b1782 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -575,6 +575,8 @@ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ +#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ + /* NVM Control */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index e23459cf3d0ee..d8453946bff8b 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -2737,6 +2737,11 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) if (hw->phy.type != e1000_phy_82578) goto out; + /* Do not apply workaround if in PHY loopback bit 14 set */ + hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data); + if (data & PHY_CONTROL_LB) + goto out; + /* check if link is up and at 1Gbps */ ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); if (ret_val) -- GitLab From fc0c7760aea07c74af3395ad18f96ba62eecac36 Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:27:55 +0000 Subject: [PATCH 0675/1002] e1000e: delay after LCD reset and proper checks for PHY configuration done A previous workaround for 82578 to avoid link stall causes some PHY registers to get cleared inadvertently. Add a delay after all LCD resets to make sure PHY registers are in a stable state before continuing. Also, after resets check the EEC register for the state of PHY configuration performed by the MAC for ICH9 and earlier parts (as done before), but check the LAN_INIT_DONE bit in the STATUS register for ICH10 and newer parts (EEC doesn't exist in these newer parts). Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/defines.h | 1 + drivers/net/e1000e/ich8lan.c | 125 +++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 4329ec34b1782..c0f185beb8bc1 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -238,6 +238,7 @@ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ +#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ /* Constants used to interpret the masked PCI-X bus speed. */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 9e23f50fb9cdf..438778fef5acc 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -693,6 +693,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) return ret_val; } +/** + * e1000_lan_init_done_ich8lan - Check for PHY config completion + * @hw: pointer to the HW structure + * + * Check the appropriate indication the MAC has finished configuring the + * PHY after a software reset. + **/ +static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) +{ + u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; + + /* Wait for basic configuration completes before proceeding */ + do { + data = er32(STATUS); + data &= E1000_STATUS_LAN_INIT_DONE; + udelay(100); + } while ((!data) && --loop); + + /* + * If basic configuration is incomplete before the above loop + * count reaches 0, loading the configuration from NVM will + * leave the PHY in a bad state possibly resulting in no link. + */ + if (loop == 0) + hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); + + /* Clear the Init Done bit for the next init event */ + data = er32(STATUS); + data &= ~E1000_STATUS_LAN_INIT_DONE; + ew32(STATUS, data); +} + /** * e1000_phy_hw_reset_ich8lan - Performs a PHY reset * @hw: pointer to the HW structure @@ -707,13 +739,15 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) u32 i; u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val; - u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT; u16 word_addr, reg_data, reg_addr, phy_page = 0; ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) return ret_val; + /* Allow time for h/w to get to a quiescent state after reset */ + mdelay(10); + if (hw->mac.type == e1000_pchlan) { ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) @@ -741,26 +775,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) if (!(data & sw_cfg_mask)) return 0; - /* Wait for basic configuration completes before proceeding*/ - do { - data = er32(STATUS); - data &= E1000_STATUS_LAN_INIT_DONE; - udelay(100); - } while ((!data) && --loop); - - /* - * If basic configuration is incomplete before the above loop - * count reaches 0, loading the configuration from NVM will - * leave the PHY in a bad state possibly resulting in no link. - */ - if (loop == 0) { - hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n"); - } - - /* Clear the Init Done bit for the next init event */ - data = er32(STATUS); - data &= ~E1000_STATUS_LAN_INIT_DONE; - ew32(STATUS, data); + /* Wait for basic configuration completes before proceeding */ + e1000_lan_init_done_ich8lan(hw); /* * Make sure HW does not configure LCD from PHY @@ -2143,6 +2159,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl = er32(CTRL); if (!e1000_check_reset_block(hw)) { + /* Clear PHY Reset Asserted bit */ + if (hw->mac.type >= e1000_pchlan) { + u32 status = er32(STATUS); + ew32(STATUS, status & ~E1000_STATUS_PHYRA); + } + /* * PHY HW reset requires MAC CORE reset at the same * time to make sure the interface between MAC and the @@ -2156,21 +2178,24 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(CTRL, (ctrl | E1000_CTRL_RST)); msleep(20); - if (!ret_val) { - /* release the swflag because it is not reset by - * hardware reset - */ + if (!ret_val) e1000_release_swflag_ich8lan(hw); - } - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) { - /* - * When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - hw_dbg(hw, "Auto Read Done did not complete\n"); + if (ctrl & E1000_CTRL_PHY_RST) + ret_val = hw->phy.ops.get_cfg_done(hw); + + if (hw->mac.type >= e1000_ich10lan) { + e1000_lan_init_done_ich8lan(hw); + } else { + ret_val = e1000e_get_auto_rd_done(hw); + if (ret_val) { + /* + * When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + hw_dbg(hw, "Auto Read Done did not complete\n"); + } } ew32(IMC, 0xffffffff); @@ -2222,6 +2247,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + /* + * The 82578 Rx buffer will stall if wakeup is enabled in host and + * the ME. Reading the BM_WUC register will clear the host wakeup bit. + * Reset the phy after disabling host wakeup to reset the Rx buffer. + */ + if (hw->phy.type == e1000_phy_82578) { + hw->phy.ops.read_phy_reg(hw, BM_WUC, &i); + ret_val = e1000_phy_hw_reset_ich8lan(hw); + if (ret_val) + return ret_val; + } + /* Setup link and flow control */ ret_val = e1000_setup_link_ich8lan(hw); @@ -2253,16 +2290,6 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) ctrl_ext |= E1000_CTRL_EXT_RO_DIS; ew32(CTRL_EXT, ctrl_ext); - /* - * The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Reading the BM_WUC register will clear the host wakeup bit. - * Reset the phy after disabling host wakeup to reset the Rx buffer. - */ - if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_WUC, &i); - e1000e_phy_hw_reset_generic(hw); - } - /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link @@ -2850,6 +2877,16 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) { u32 bank = 0; + if (hw->mac.type >= e1000_pchlan) { + u32 status = er32(STATUS); + + if (status & E1000_STATUS_PHYRA) + ew32(STATUS, status & ~E1000_STATUS_PHYRA); + else + hw_dbg(hw, + "PHY Reset Asserted not set - needs delay\n"); + } + e1000e_get_cfg_done(hw); /* If EEPROM is not marked present, init the IGP 3 PHY manually */ -- GitLab From 60f1292fcbdff03ef5caea56404d3d81d05026f6 Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:28:14 +0000 Subject: [PATCH 0676/1002] e1000e: do not write SmartSpeed register bits on parts without support The driver was accessing register bits for features on parts that do not support that feature. This could cause problems in the hardware. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/ich8lan.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 438778fef5acc..bf9b97db76b96 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -977,12 +977,14 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * Call gig speed drop workaround on LPLU before accessing * any PHY registers */ - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3)) + if (hw->mac.type == e1000_ich8lan) e1000e_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ @@ -995,6 +997,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most @@ -1054,6 +1059,10 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (!active) { phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + + if (phy->type != e1000_phy_igp_3) + return 0; + /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most @@ -1089,12 +1098,14 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; ew32(PHY_CTRL, phy_ctrl); + if (phy->type != e1000_phy_igp_3) + return 0; + /* * Call gig speed drop workaround on LPLU before accessing * any PHY registers */ - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3)) + if (hw->mac.type == e1000_ich8lan) e1000e_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ -- GitLab From 28c9195a570a32de2760310ca278d44a4fd060a4 Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:28:32 +0000 Subject: [PATCH 0677/1002] e1000e: prevent NVM corruption on sectors larger than 4K Limit NVM writes to 4K sections to prevent NVM corruption on larger sector allocations (up to 64K). Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/ich8lan.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index bf9b97db76b96..0e0755f0db3fd 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -338,6 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + union ich8_hws_flash_status hsfsts; u32 gfpreg; u32 sector_base_addr; u32 sector_end_addr; @@ -374,6 +375,20 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); + /* + * Make sure the flash bank size does not overwrite the 4k + * sector ranges. We may have 64k allotted to us but we only care + * about the first 2 4k sectors. Therefore, if we have anything less + * than 64k set in the HSFSTS register, we will reduce the bank size + * down to 4k and let the rest remain unused. If berasesz == 3, then + * we are working in 64k mode. Otherwise we are not. + */ + if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) { + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.berasesz != 3) + nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS; + } + nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; /* Clear shadow ram */ @@ -1932,7 +1947,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) break; case 1: sector_size = ICH_FLASH_SEG_SIZE_4K; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; + iteration = 1; break; case 2: if (hw->mac.type == e1000_ich9lan) { @@ -1944,7 +1959,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) break; case 3: sector_size = ICH_FLASH_SEG_SIZE_64K; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; + iteration = 1; break; default: return -E1000_ERR_NVM; -- GitLab From 906e8d9792b1c4a8b58c1383f4c00fc4c9936fc3 Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:28:50 +0000 Subject: [PATCH 0678/1002] e1000e: delay second read of PHY_STATUS register on failure of first read Some PHYs may require two reads of the PHY_STATUS register to determine the link status. If the PHY is being accessed by another thread it is possible the first read could timeout and fail. In this case, put a delay in so the second read will pick up the correct link status. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/phy.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index d8453946bff8b..994401fd0664f 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -1531,7 +1531,12 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, */ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); if (ret_val) - break; + /* + * If the first read fails, another entity may have + * ownership of the resources, wait and try again to + * see if they have relinquished the resources yet. + */ + udelay(usec_interval); ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); if (ret_val) break; -- GitLab From 7d3cabbcc86f7f69c47cb20c23ee84350ae6cfbb Mon Sep 17 00:00:00 2001 From: Bruce Allan <bruce.w.allan@intel.com> Date: Wed, 1 Jul 2009 13:29:08 +0000 Subject: [PATCH 0679/1002] e1000e: disable K1 at 1000Mbps for 82577/82578 This workaround is required for an issue in hardware where noise on the interconnect between the MAC and PHY could be generated by a lower power mode (K1) at 1000Mbps resulting in bad packets. Disable K1 while at 1000 Mbps but keep it enabled for 10/100Mbps and when the cable is disconnected. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/e1000e/hw.h | 4 ++ drivers/net/e1000e/ich8lan.c | 107 ++++++++++++++++++++++++++++++++++- drivers/net/e1000e/lib.c | 6 -- 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 163c1c0cfee70..fd44d9f907696 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -215,6 +215,7 @@ enum e1e_registers { E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ + E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ E1000_HICR = 0x08F00, /* Host Interface Control */ }; @@ -302,6 +303,9 @@ enum e1e_registers { #define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ +#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 +#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E +#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 0e0755f0db3fd..d56c7473144a6 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -461,6 +461,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) return 0; } +/** + * e1000_check_for_copper_link_ich8lan - Check for link (Copper) + * @hw: pointer to the HW structure + * + * Checks to see of the link status of the hardware has changed. If a + * change in link status has been detected, then we read the PHY registers + * to get the current speed/duplex if link exists. + **/ +static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) +{ + struct e1000_mac_info *mac = &hw->mac; + s32 ret_val; + bool link; + + /* + * We only want to go out to the PHY registers to see if Auto-Neg + * has completed and/or if our link status has changed. The + * get_link_status flag is set upon receiving a Link Status + * Change or Rx Sequence Error interrupt. + */ + if (!mac->get_link_status) { + ret_val = 0; + goto out; + } + + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_ENABLE); + if (ret_val) + goto out; + } + + /* + * First we want to see if the MII Status Register reports + * link. If so, then we want to get the current speed/duplex + * of the PHY. + */ + ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) + goto out; /* No link detected */ + + mac->get_link_status = false; + + if (hw->phy.type == e1000_phy_82578) { + ret_val = e1000_link_stall_workaround_hv(hw); + if (ret_val) + goto out; + } + + /* + * Check if there was DownShift, must be checked + * immediately after link-up + */ + e1000e_check_downshift(hw); + + /* + * If we are forcing speed/duplex, then we simply return since + * we have already determined whether we have link or not. + */ + if (!mac->autoneg) { + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + /* + * Auto-Neg is enabled. Auto Speed Detection takes care + * of MAC speed/duplex configuration. So we only need to + * configure Collision Distance in the MAC. + */ + e1000e_config_collision_dist(hw); + + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000e_config_fc_after_link_up(hw); + if (ret_val) + hw_dbg(hw, "Error configuring flow control\n"); + +out: + return ret_val; +} + static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; @@ -2224,6 +2313,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) } } + /* + * For PCH, this write will make sure that any noise + * will be detected as a CRC error and be dropped rather than show up + * as a bad packet to the DMA engine. + */ + if (hw->mac.type == e1000_pchlan) + ew32(CRC_OFFSET, 0x65656565); + ew32(IMC, 0xffffffff); icr = er32(ICR); @@ -2538,6 +2635,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, if (ret_val) return ret_val; + if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { + ret_val = e1000e_write_kmrn_reg(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + E1000_KMRNCTRLSTA_K1_DISABLE); + if (ret_val) + return ret_val; + } + if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { @@ -2984,7 +3089,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) static struct e1000_mac_operations ich8_mac_ops = { .id_led_init = e1000e_id_led_init, .check_mng_mode = e1000_check_mng_mode_ich8lan, - .check_for_link = e1000e_check_for_copper_link, + .check_for_link = e1000_check_for_copper_link_ich8lan, /* cleanup_led dependent on mac type */ .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, .get_bus_info = e1000_get_bus_info_ich8lan, diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index be6d9e9903741..99ba2b8a2a054 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) mac->get_link_status = 0; - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1000_link_stall_workaround_hv(hw); - if (ret_val) - return ret_val; - } - /* * Check if there was DownShift, must be checked * immediately after link-up -- GitLab From c001c213b109c8baeeb6d012b422bf059b18368f Mon Sep 17 00:00:00 2001 From: Sathya Perla <sathyap@serverengines.com> Date: Wed, 1 Jul 2009 01:06:07 +0000 Subject: [PATCH 0680/1002] be2net: fix spurious interrupt handling in intx mode Occasionally we may see an interrupt without an event in the eq. In intx, we currently see the event queue and return IRQ_NONE causing a the irq to be disabled ("no one cared".) Instead, read the CEV_ISR reg to check the existence of the interrupt. Signed-off-by: Sathya Perla <sathyap@serverengines.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/benet/be_hw.h | 4 ++++ drivers/net/benet/be_main.c | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index b02e805c1db37..29c33c709c6d1 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -55,6 +55,10 @@ #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 +/********* ISR0 Register offset **********/ +#define CEV_ISR0_OFFSET 0xC18 +#define CEV_ISR_SIZE 4 + /********* Event Q door bell *************/ #define DB_EQ_OFFSET DB_CQ_OFFSET #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 308eb09ca56bb..c43f6a1192950 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1274,15 +1274,17 @@ static irqreturn_t be_intx(int irq, void *dev) { struct be_adapter *adapter = dev; struct be_ctrl_info *ctrl = &adapter->ctrl; - int rx, tx; + int isr; - tx = event_handle(ctrl, &adapter->tx_eq); - rx = event_handle(ctrl, &adapter->rx_eq); + isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + + ctrl->pci_func * CEV_ISR_SIZE); + if (!isr) + return IRQ_NONE; - if (rx || tx) - return IRQ_HANDLED; - else - return IRQ_NONE; + event_handle(ctrl, &adapter->tx_eq); + event_handle(ctrl, &adapter->rx_eq); + + return IRQ_HANDLED; } static irqreturn_t be_msix_rx(int irq, void *dev) -- GitLab From 5a5e02a614e59db7536cd11029e6674adc41b191 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 09:35:44 +0100 Subject: [PATCH 0681/1002] intel-iommu: Fix dma vs. mm page confusion with aligned_nrpages() The aligned_nrpages() function rounds up to the next VM page, but returns its result as a number of DMA pages. Purely theoretical except on IA64, which doesn't boot with VT-d right now anyway. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 53075424a4349..ad85e95d2dcc2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2368,15 +2368,15 @@ int __init init_dmars(void) return ret; } +/* Returns a number of VTD pages, but aligned to MM page size */ static inline unsigned long aligned_nrpages(unsigned long host_addr, size_t size) { host_addr &= ~PAGE_MASK; - host_addr += size + PAGE_SIZE - 1; - - return host_addr >> VTD_PAGE_SHIFT; + return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT; } +/* This takes a number of _MM_ pages, not VTD pages */ static struct iova *intel_alloc_iova(struct device *dev, struct dmar_domain *domain, unsigned long nrpages, uint64_t dma_mask) @@ -2506,7 +2506,8 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, iommu = domain_get_iommu(domain); size = aligned_nrpages(paddr, size); - iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), + pdev->dma_mask); if (!iova) goto error; @@ -2797,7 +2798,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne for_each_sg(sglist, sg, nelems, i) size += aligned_nrpages(sg->offset, sg->length); - iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); + iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), + pdev->dma_mask); if (!iova) { sglist->dma_length = 0; return 0; -- GitLab From 1e4c64c46d413de84cc0b786bd6a9b555ba7d111 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 10:40:38 +0100 Subject: [PATCH 0682/1002] intel-iommu: Don't set identity mapping for bypassed graphics devices We should check iommu_dummy() _first_, because that means it's attached to an iommu that we've just disabled completely. At the moment, we might try to put the device into the identity mapping domain. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ad85e95d2dcc2..3e3910127fc13 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2447,8 +2447,11 @@ static int iommu_no_mapping(struct pci_dev *pdev) { int found; + if (iommu_dummy(pdev)) + return 1; + if (!iommu_identity_mapping) - return iommu_dummy(pdev); + return 0; found = identity_mapping(pdev); if (found) { @@ -2480,7 +2483,7 @@ static int iommu_no_mapping(struct pci_dev *pdev) } } - return iommu_dummy(pdev); + return 0; } static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, -- GitLab From a79f0da80a508448434476b77f9d3d1a469eab67 Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 3 Jul 2009 16:50:10 +0200 Subject: [PATCH 0683/1002] x86: atomic64: Inline atomic64_read() again Now atomic64_read() is light weight (no register pressure and small icache), we can inline it again. Also use "=&A" constraint instead of "+A" to avoid warning about unitialized 'res' variable. (gcc had to force 0 in eax/edx) $ size vmlinux.prev vmlinux.after text data bss dec hex filename 4908667 451676 1684868 7045211 6b805b vmlinux.prev 4908651 451676 1684868 7045195 6b804b vmlinux.after Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <4A4E1AA2.30002@gmail.com> [ Also fix typo in atomic64_set() export ] Signed-off-by: Ingo Molnar <mingo@elte.hu> --- arch/x86/include/asm/atomic_32.h | 22 ++++++++++++++++++++++ arch/x86/lib/atomic64_32.c | 23 +---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h index d7c8849b8c674..dc5a667ff7913 100644 --- a/arch/x86/include/asm/atomic_32.h +++ b/arch/x86/include/asm/atomic_32.h @@ -295,6 +295,28 @@ extern void atomic64_set(atomic64_t *ptr, u64 new_val); * * Atomically reads the value of @ptr and returns it. */ +static inline u64 atomic64_read(atomic64_t *ptr) +{ + u64 res; + + /* + * Note, we inline this atomic64_t primitive because + * it only clobbers EAX/EDX and leaves the others + * untouched. We also (somewhat subtly) rely on the + * fact that cmpxchg8b returns the current 64-bit value + * of the memory location we are touching: + */ + asm volatile( + "mov %%ebx, %%eax\n\t" + "mov %%ecx, %%edx\n\t" + LOCK_PREFIX "cmpxchg8b %1\n" + : "=&A" (res) + : "m" (*ptr) + ); + + return res; +} + extern u64 atomic64_read(atomic64_t *ptr); /** diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index 1d98c9eb6eacb..824fa0be55a39 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -66,31 +66,10 @@ void atomic64_set(atomic64_t *ptr, u64 new_val) { atomic64_xchg(ptr, new_val); } -EXPORT_SYMBOL(atomic64_read); +EXPORT_SYMBOL(atomic64_set); /** - * atomic64_read - read atomic64 variable - * @ptr: pointer to type atomic64_t - * - * Atomically reads the value of @ptr and returns it. - */ -u64 atomic64_read(atomic64_t *ptr) -{ - u64 res; - - asm volatile( - "mov %%ebx, %%eax\n\t" - "mov %%ecx, %%edx\n\t" - LOCK_PREFIX "cmpxchg8b %1\n" - : "+A" (res) - : "m" (*ptr) - ); - - return res; -} EXPORT_SYMBOL(atomic64_read); - -/** * atomic64_add_return - add and return * @delta: integer value to add * @ptr: pointer to type atomic64_t -- GitLab From 1b7bc0a1618b4de1e6f55c6d95b790f4ab6fcd9e Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 10:49:46 +0100 Subject: [PATCH 0684/1002] intel-iommu: Fix reattaching of devices to identity mapping domain When we reattach a device to the si_domain (because it's been removed from a VM), we weren't calling domain_context_mapping() to actually tell the hardware about that. We should really put the call to domain_context_mapping() into domain_add_dev_info() -- we never call the latter without also doing the former, and we can keep the error paths simple that way. But that's a cleanup which can wait for 2.6.32 now. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3e3910127fc13..73a5c71dd37d6 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2475,6 +2475,9 @@ static int iommu_no_mapping(struct pci_dev *pdev) if (pdev->dma_mask > DMA_BIT_MASK(32)) { int ret; ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return 0; + ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); if (!ret) { printk(KERN_INFO "64bit %s uses identity mapping\n", pci_name(pdev)); -- GitLab From 40e4aa34324bff3938a900014254f88943d05e15 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 10:55:41 +0100 Subject: [PATCH 0685/1002] intel-iommu: Add iommu_should_identity_map() function We do this twice, and it's about to get more complicated. This makes the code slightly clearer about what it's doing, too. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 73a5c71dd37d6..ae5ccdf8b19f1 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2442,6 +2442,11 @@ static int iommu_dummy(struct pci_dev *pdev) return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; } +static int iommu_should_identity_map(struct pci_dev *pdev) +{ + return pdev->dma_mask > DMA_BIT_MASK(32); +} + /* Check if the pdev needs to go through non-identity map and unmap process.*/ static int iommu_no_mapping(struct pci_dev *pdev) { @@ -2455,7 +2460,7 @@ static int iommu_no_mapping(struct pci_dev *pdev) found = identity_mapping(pdev); if (found) { - if (pdev->dma_mask > DMA_BIT_MASK(32)) + if (iommu_should_identity_map(pdev)) return 1; else { /* @@ -2472,7 +2477,7 @@ static int iommu_no_mapping(struct pci_dev *pdev) * In case of a detached 64 bit DMA device from vm, the device * is put into si_domain for identity mapping. */ - if (pdev->dma_mask > DMA_BIT_MASK(32)) { + if (iommu_should_identity_map(pdev)) { int ret; ret = domain_add_dev_info(si_domain, pdev); if (ret) -- GitLab From 62edf5dc4a524e4cb525e6020b955a1ad593d9ba Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 10:59:46 +0100 Subject: [PATCH 0686/1002] intel-iommu: Restore DMAR_BROKEN_GFX_WA option for broken graphics drivers We need to give people a little more time to fix the broken drivers. Re-introduce this, but tied in properly with the 'iommu=pt' support this time. Change the config option name and make it default to 'no' too. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- arch/x86/Kconfig | 12 ++++++++++++ drivers/pci/intel-iommu.c | 29 +++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c07f722059094..738bdc6b0f8b8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1913,6 +1913,18 @@ config DMAR_DEFAULT_ON recommended you say N here while the DMAR code remains experimental. +config DMAR_BROKEN_GFX_WA + def_bool n + prompt "Workaround broken graphics drivers (going away soon)" + depends on DMAR + ---help--- + Current Graphics drivers tend to use physical address + for DMA and avoid using DMA APIs. Setting this config + option permits the IOMMU driver to set a unity map for + all the OS-visible memory. Hence the driver can continue + to use physical addresses for DMA, at least until this + option is removed in the 2.6.32 kernel. + config DMAR_FLOPPY_WA def_bool y depends on DMAR diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index ae5ccdf8b19f1..5ee8305257eaf 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2127,16 +2127,18 @@ static int iommu_prepare_static_identity_mapping(void) return -EFAULT; for_each_pci_dev(pdev) { - printk(KERN_INFO "IOMMU: identity mapping for device %s\n", - pci_name(pdev)); + if (iommu_identity_mapping == 1 || IS_GFX_DEVICE(pdev)) { + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", + pci_name(pdev)); - ret = domain_context_mapping(si_domain, pdev, - CONTEXT_TT_MULTI_LEVEL); - if (ret) - return ret; - ret = domain_add_dev_info(si_domain, pdev); - if (ret) - return ret; + ret = domain_context_mapping(si_domain, pdev, + CONTEXT_TT_MULTI_LEVEL); + if (ret) + return ret; + ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return ret; + } } return 0; @@ -2291,6 +2293,10 @@ int __init init_dmars(void) * identity mapping if iommu_identity_mapping is set. */ if (!iommu_pass_through) { +#ifdef CONFIG_DMAR_BROKEN_GFX_WA + if (!iommu_identity_mapping) + iommu_identity_mapping = 2; +#endif if (iommu_identity_mapping) iommu_prepare_static_identity_mapping(); /* @@ -2444,7 +2450,10 @@ static int iommu_dummy(struct pci_dev *pdev) static int iommu_should_identity_map(struct pci_dev *pdev) { - return pdev->dma_mask > DMA_BIT_MASK(32); + if (iommu_identity_mapping == 2) + return IS_GFX_DEVICE(pdev); + else + return pdev->dma_mask > DMA_BIT_MASK(32); } /* Check if the pdev needs to go through non-identity map and unmap process.*/ -- GitLab From 02358fcfa54ce018a0bb56ca9f5a898de574a9d3 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Date: Sat, 4 Jul 2009 01:44:59 -0300 Subject: [PATCH 0687/1002] ALSA: hda - move 8086:fb30 quirk (stac9205) to the proper section Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_sigmatel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 14f3c3e0f62de..41b5b3a18c1ee 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1590,8 +1590,6 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30, - "SigmaTel",STAC_9205_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), /* Dell laptops have BIOS problem */ @@ -2344,6 +2342,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_9205_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30, + "SigmaTel", STAC_9205_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_9205_REF), /* Dell */ -- GitLab From 736768325efcbee7b0861d62670d01a54c2d158b Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 14:08:36 +0100 Subject: [PATCH 0688/1002] intel-iommu: No mapping for non-PCI devices This should fix kernel.org bug #11821, where the dcdbas driver makes up a platform device and then uses dma_alloc_coherent() on it, in an attempt to get memory < 4GiB. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 5ee8305257eaf..fa052dd89913d 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2457,10 +2457,15 @@ static int iommu_should_identity_map(struct pci_dev *pdev) } /* Check if the pdev needs to go through non-identity map and unmap process.*/ -static int iommu_no_mapping(struct pci_dev *pdev) +static int iommu_no_mapping(struct device *dev) { + struct pci_dev *pdev; int found; + if (unlikely(dev->bus != &pci_bus_type)) + return 1; + + pdev = to_pci_dev(dev); if (iommu_dummy(pdev)) return 1; @@ -2516,7 +2521,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, BUG_ON(dir == DMA_NONE); - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return paddr; domain = get_valid_domain_for_dev(pdev); @@ -2656,7 +2661,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, struct iova *iova; struct intel_iommu *iommu; - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(dev)) return; domain = find_domain(pdev); @@ -2747,7 +2752,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, struct iova *iova; struct intel_iommu *iommu; - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return; domain = find_domain(pdev); @@ -2806,7 +2811,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne struct intel_iommu *iommu; BUG_ON(dir == DMA_NONE); - if (iommu_no_mapping(pdev)) + if (iommu_no_mapping(hwdev)) return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); domain = get_valid_domain_for_dev(pdev); -- GitLab From 64614e66fbfcaa57598c1678d699520dfbf4f531 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@igel.co.jp> Date: Fri, 3 Jul 2009 09:12:46 +0000 Subject: [PATCH 0689/1002] usb: allow sh7724 to enable on-chip r8a66597 The sh7724 processor has two on-chip r8a66597 blocks, so add it to the list of processors for SUPERH_ON_CHIP_R8A66597. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/usb/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1576a0520adf3..0c03471f0d419 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -337,10 +337,10 @@ config USB_R8A66597_HCD config SUPERH_ON_CHIP_R8A66597 boolean "Enable SuperH on-chip R8A66597 USB" - depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723) + depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724) help This driver enables support for the on-chip R8A66597 in the - SH7366 and SH7723 processors. + SH7366, SH7723 and SH7724 processors. config USB_WHCI_HCD tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" -- GitLab From 9731f4a202f29ff402ea2ddad7ff6f3a559c0c82 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@igel.co.jp> Date: Fri, 3 Jul 2009 09:40:03 +0000 Subject: [PATCH 0690/1002] sh: add r8a66597 usb0 host to the se7724 board Add USB host support for port CN27 on the Solution Engine 7724 board. The r8a66597-hcd driver is hooked up as a platform device and some registers are configured to enable the USB host function. The hardware driving the USB port is the on-chip USB0 block in the sh7724 processor configured as USB host controller. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/boards/mach-se/7724/setup.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index c050a8d76dfd1..8fed45a2fb855 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -19,6 +19,7 @@ #include <linux/smc91x.h> #include <linux/gpio.h> #include <linux/input.h> +#include <linux/usb/r8a66597.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> #include <asm/io.h> @@ -302,6 +303,34 @@ static struct platform_device sh_eth_device = { .resource = sh_eth_resources, }; +static struct r8a66597_platdata sh7724_usb0_host_data = { +}; + +static struct resource sh7724_usb0_host_resources[] = { + [0] = { + .start = 0xa4d80000, + .end = 0xa4d800ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 65, + .end = 65, + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, + }, +}; + +static struct platform_device sh7724_usb0_host_device = { + .name = "r8a66597_hcd", + .id = 0, + .dev = { + .dma_mask = NULL, /* not use dma */ + .coherent_dma_mask = 0xffffffff, + .platform_data = &sh7724_usb0_host_data, + }, + .num_resources = ARRAY_SIZE(sh7724_usb0_host_resources), + .resource = sh7724_usb0_host_resources, +}; + static struct platform_device *ms7724se_devices[] __initdata = { &heartbeat_device, &smc91x_eth_device, @@ -311,6 +340,7 @@ static struct platform_device *ms7724se_devices[] __initdata = { &ceu1_device, &keysc_device, &sh_eth_device, + &sh7724_usb0_host_device, }; #define EEPROM_OP 0xBA206000 @@ -364,6 +394,7 @@ static void __init sh_eth_init(void) #define SW4140 0xBA201000 #define FPGA_OUT 0xBA200400 #define PORT_HIZA 0xA4050158 +#define PORT_MSELCRB 0xA4050182 #define SW41_A 0x0100 #define SW41_B 0x0200 @@ -373,6 +404,7 @@ static void __init sh_eth_init(void) #define SW41_F 0x2000 #define SW41_G 0x4000 #define SW41_H 0x8000 + static int __init devices_setup(void) { u16 sw = ctrl_inw(SW4140); /* select camera, monitor */ @@ -385,6 +417,12 @@ static int __init devices_setup(void) (1 << 14)), /* RMII */ FPGA_OUT); + /* turn on USB clocks, use external clock */ + ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB); + + /* enable USB0 port */ + ctrl_outw(0x0600, 0xa40501d4); + /* enable IRQ 0,1,2 */ gpio_request(GPIO_FN_INTC_IRQ0, NULL); gpio_request(GPIO_FN_INTC_IRQ1, NULL); -- GitLab From f50bf2b2f5e83b794e0bdb2f3f589f55ef0d52d0 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Fri, 3 Jul 2009 15:45:56 +0900 Subject: [PATCH 0691/1002] video: sm501fb: Early initialization of mm_lock mutex. Commit 537a1bf059fa312355696fa6db80726e655e7f17 (fbdev: add mutex for fb_mmap locking) introduces a ->mm_lock mutex for protecting smem assignments. Unfortunately in the case of sm501fb these happen quite early in the initialization code, well before the mutex_init() that takes place in register_framebuffer(), leading to: Badness at kernel/mutex.c:207 Pid : 1, Comm: swapper CPU : 0 Not tainted (2.6.31-rc1-00284-g529ba0d-dirty #2273) PC is at __mutex_lock_slowpath+0x72/0x1bc PR is at __mutex_lock_slowpath+0x66/0x1bc ... matroxfb appears to have the same issue and has solved it with an early mutex_init(), so we do the same for sm501fb. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Cc: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/sm501fb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 98f24f0ec00df..16d4f4c7d52b5 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1624,6 +1624,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info, if (!fbi) return 0; + mutex_init(&info->fb[head]->mm_lock); + ret = sm501fb_init_fb(info->fb[head], head, drvname); if (ret) { dev_err(info->dev, "cannot initialise fb %s\n", drvname); -- GitLab From 8e4a718ff38d8539938ec3421935904c27e00c39 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Sat, 4 Jul 2009 10:58:48 -0700 Subject: [PATCH 0692/1002] Linux 2.6.31-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b4c7ef5ab431d..0aeec59c1f0a8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 31 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* -- GitLab From 6941af2810c6fc970b88f7c0d52ba4e286acbee5 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 18:24:27 +0100 Subject: [PATCH 0693/1002] intel-iommu: Use iommu_should_identity_map() at startup time too. At boot time, the dma_mask won't have been set on any devices, so we assume that all devices will be 64-bit capable (and thus get a 1:1 map). Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fa052dd89913d..f9fc4f3bfa3f4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2117,6 +2117,17 @@ static int domain_add_dev_info(struct dmar_domain *domain, return 0; } +static int iommu_should_identity_map(struct pci_dev *pdev, int startup) +{ + if (iommu_identity_mapping == 2) + return IS_GFX_DEVICE(pdev); + + if (!startup) + return pdev->dma_mask > DMA_BIT_MASK(32); + + return 1; +} + static int iommu_prepare_static_identity_mapping(void) { struct pci_dev *pdev = NULL; @@ -2127,7 +2138,7 @@ static int iommu_prepare_static_identity_mapping(void) return -EFAULT; for_each_pci_dev(pdev) { - if (iommu_identity_mapping == 1 || IS_GFX_DEVICE(pdev)) { + if (iommu_should_identity_map(pdev, 1)) { printk(KERN_INFO "IOMMU: identity mapping for device %s\n", pci_name(pdev)); @@ -2448,14 +2459,6 @@ static int iommu_dummy(struct pci_dev *pdev) return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; } -static int iommu_should_identity_map(struct pci_dev *pdev) -{ - if (iommu_identity_mapping == 2) - return IS_GFX_DEVICE(pdev); - else - return pdev->dma_mask > DMA_BIT_MASK(32); -} - /* Check if the pdev needs to go through non-identity map and unmap process.*/ static int iommu_no_mapping(struct device *dev) { @@ -2474,7 +2477,7 @@ static int iommu_no_mapping(struct device *dev) found = identity_mapping(pdev); if (found) { - if (iommu_should_identity_map(pdev)) + if (iommu_should_identity_map(pdev, 0)) return 1; else { /* @@ -2491,7 +2494,7 @@ static int iommu_no_mapping(struct device *dev) * In case of a detached 64 bit DMA device from vm, the device * is put into si_domain for identity mapping. */ - if (iommu_should_identity_map(pdev)) { + if (iommu_should_identity_map(pdev, 0)) { int ret; ret = domain_add_dev_info(si_domain, pdev); if (ret) -- GitLab From 3dfc813d94bba2046c6aed216e0fd69ac93a8e03 Mon Sep 17 00:00:00 2001 From: David Woodhouse <David.Woodhouse@intel.com> Date: Sat, 4 Jul 2009 19:11:08 +0100 Subject: [PATCH 0694/1002] intel-iommu: Don't use identity mapping for PCI devices behind bridges Our current strategy for pass-through mode is to put all devices into the 1:1 domain at startup (which is before we know what their dma_mask will be), and only _later_ take them out of that domain, if it turns out that they really can't address all of memory. However, when there are a bunch of PCI devices behind a bridge, they all end up with the same source-id on their DMA transactions, and hence in the same IOMMU domain. This means that we _can't_ easily move them from the 1:1 domain into their own domain at runtime, because there might be DMA in-flight from their siblings. So we have to adjust our pass-through strategy: For PCI devices not on the root bus, and for the bridges which will take responsibility for their transactions, we have to start up _out_ of the 1:1 domain, just in case. This fixes the BUG() we see when we have 32-bit-capable devices behind a PCI-PCI bridge, and use the software identity mapping. It does mean that we might end up using 'normal' mapping mode for some devices which could actually live with the faster 1:1 mapping -- but this is only for PCI devices behind bridges, which presumably aren't the devices for which people are most concerned about performance. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> --- drivers/pci/intel-iommu.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f9fc4f3bfa3f4..360fb67a30d7a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -2122,6 +2122,36 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) if (iommu_identity_mapping == 2) return IS_GFX_DEVICE(pdev); + /* + * We want to start off with all devices in the 1:1 domain, and + * take them out later if we find they can't access all of memory. + * + * However, we can't do this for PCI devices behind bridges, + * because all PCI devices behind the same bridge will end up + * with the same source-id on their transactions. + * + * Practically speaking, we can't change things around for these + * devices at run-time, because we can't be sure there'll be no + * DMA transactions in flight for any of their siblings. + * + * So PCI devices (unless they're on the root bus) as well as + * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of + * the 1:1 domain, just in _case_ one of their siblings turns out + * not to be able to map all of memory. + */ + if (!pdev->is_pcie) { + if (!pci_is_root_bus(pdev->bus)) + return 0; + if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) + return 0; + } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + return 0; + + /* + * At boot time, we don't yet know if devices will be 64-bit capable. + * Assume that they will -- if they turn out not to be, then we can + * take them out of the 1:1 domain later. + */ if (!startup) return pdev->dma_mask > DMA_BIT_MASK(32); -- GitLab From febe04de3be4bf66f9339d8847db2806d99fd164 Mon Sep 17 00:00:00 2001 From: Akinobu Mita <akinobu.mita@gmail.com> Date: Wed, 1 Jul 2009 11:13:07 +0900 Subject: [PATCH 0695/1002] x86: fix usage of bios intcall() Some intcall() misuses the input biosregs as output in cf06de7b9cdd3efee7a59dced1977b3c21d43732 This fixes the problem vga=ask boot option doesn't show enough modes. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> LKML-Reference: <20090701021307.GA3127@localhost.localdomain> Signed-off-by: H. Peter Anvin <hpa@zytor.com> --- arch/x86/boot/video-bios.c | 3 +-- arch/x86/boot/video-vesa.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c index d660be4923634..49e0c18833e0d 100644 --- a/arch/x86/boot/video-bios.c +++ b/arch/x86/boot/video-bios.c @@ -37,14 +37,13 @@ static int set_bios_mode(u8 mode) ireg.al = mode; /* AH=0x00 Set Video Mode */ intcall(0x10, &ireg, NULL); - ireg.ah = 0x0f; /* Get Current Video Mode */ intcall(0x10, &ireg, &oreg); do_restore = 1; /* Assume video contents were lost */ /* Not all BIOSes are clean with the top bit */ - new_mode = ireg.al & 0x7f; + new_mode = oreg.al & 0x7f; if (new_mode == mode) return 0; /* Mode change OK */ diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index c700147d6ffb2..275dd177f1985 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -45,7 +45,7 @@ static int vesa_probe(void) ireg.di = (size_t)&vginfo; intcall(0x10, &ireg, &oreg); - if (ireg.ax != 0x004f || + if (oreg.ax != 0x004f || vginfo.signature != VESA_MAGIC || vginfo.version < 0x0102) return 0; /* Not present */ @@ -70,7 +70,7 @@ static int vesa_probe(void) ireg.di = (size_t)&vminfo; intcall(0x10, &ireg, &oreg); - if (ireg.ax != 0x004f) + if (oreg.ax != 0x004f) continue; if ((vminfo.mode_attr & 0x15) == 0x05) { -- GitLab From 0cfae3d8795f388f9de78adb0171520d19da77e9 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Date: Thu, 18 Jun 2009 11:42:53 +0900 Subject: [PATCH 0696/1002] nilfs2: remove unlikely directive causing mis-conversion of error code The following error code handling in nilfs_segctor_write() function wrongly converted negative error codes to a truth value (i.e. 1): err = unlikely(err) ? : res; which originaly meant to be err = err ? : res; This mis-conversion caused that write or sync functions receive the unexpected error code. This fixes the bug by removing the unlikely directive. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: stable@kernel.org --- fs/nilfs2/segment.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index aa977549919ec..c1824915c1c7b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1829,8 +1829,8 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, err = nilfs_segbuf_write(segbuf, &wi); res = nilfs_segbuf_wait(segbuf, &wi); - err = unlikely(err) ? : res; - if (unlikely(err)) + err = err ? : res; + if (err) return err; } return 0; -- GitLab From 8227b29722fdbac72357aae155d171a5c777670c Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Date: Thu, 18 Jun 2009 23:52:23 +0900 Subject: [PATCH 0697/1002] nilfs2: fix hang problem of log writer which occurs after write failures Leandro Lucarella gave me a report that nilfs gets stuck after its write function fails. The problem turned out to be caused by bugs which leave writeback flag on pages. This fixes the problem by ensuring to clear the writeback flag in error path. Reported-by: Leandro Lucarella <llucax@gmail.com> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: stable@kernel.org --- fs/nilfs2/segment.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index c1824915c1c7b..8b5e4778cf28b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1836,19 +1836,6 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, return 0; } -static int nilfs_page_has_uncleared_buffer(struct page *page) -{ - struct buffer_head *head, *bh; - - head = bh = page_buffers(page); - do { - if (buffer_dirty(bh) && !list_empty(&bh->b_assoc_buffers)) - return 1; - bh = bh->b_this_page; - } while (bh != head); - return 0; -} - static void __nilfs_end_page_io(struct page *page, int err) { if (!err) { @@ -1872,12 +1859,11 @@ static void nilfs_end_page_io(struct page *page, int err) if (!page) return; - if (buffer_nilfs_node(page_buffers(page)) && - nilfs_page_has_uncleared_buffer(page)) - /* For b-tree node pages, this function may be called twice - or more because they might be split in a segment. - This check assures that cleanup has been done for all - buffers in a split btnode page. */ + if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) + /* + * For b-tree node pages, this function may be called twice + * or more because they might be split in a segment. + */ return; __nilfs_end_page_io(page, err); @@ -1940,7 +1926,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, } if (bh->b_page != fs_page) { nilfs_end_page_io(fs_page, err); - if (unlikely(fs_page == failed_page)) + if (fs_page && fs_page == failed_page) goto done; fs_page = bh->b_page; } -- GitLab From 4a52df779700080de4afb0436d9dd9188514a69b Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Date: Thu, 18 Jun 2009 23:53:25 +0900 Subject: [PATCH 0698/1002] nilfs2: fix incorrect KERN_CRIT messages in case of write failures In case of write-failure retries, the following KERN_CRIT level messages are mistakenly output by nilfs_dat_commit_start() function: nilfs_dat_commit_start: vbn = 408463, start = 12506, end = 18446744073709551615, pbn = 530210 nilfs_dat_commit_start: vbn = 408515, start = 12506, end = 18446744073709551615, pbn = 530211 nilfs_dat_commit_start: vbn = 408464, start = 12506, end = 18446744073709551615, pbn = 530212 ... This suppresses these messages. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: stable@kernel.org --- fs/nilfs2/dat.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 0b2710e2d5654..8927ca27e6f79 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -134,15 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, req->pr_entry_bh, kaddr); entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat)); - if (entry->de_blocknr != cpu_to_le64(0) || - entry->de_end != cpu_to_le64(NILFS_CNO_MAX)) { - printk(KERN_CRIT - "%s: vbn = %llu, start = %llu, end = %llu, pbn = %llu\n", - __func__, (unsigned long long)req->pr_entry_nr, - (unsigned long long)le64_to_cpu(entry->de_start), - (unsigned long long)le64_to_cpu(entry->de_end), - (unsigned long long)le64_to_cpu(entry->de_blocknr)); - } entry->de_blocknr = cpu_to_le64(blocknr); kunmap_atomic(kaddr, KM_USER0); -- GitLab From ff54de363afa4583e2a6249f25fe21dfaeb11ea2 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Date: Fri, 19 Jun 2009 02:53:56 +0900 Subject: [PATCH 0699/1002] nilfs2: fix lockdep warning between regular file and inode file This will fix the following false positive of recursive locking which lockdep has detected: ============================================= [ INFO: possible recursive locking detected ] 2.6.30-nilfs #42 --------------------------------------------- nilfs_cleanerd/10607 is trying to acquire lock: (&bmap->b_sem){++++-.}, at: [<e0d025b7>] nilfs_bmap_lookup_at_level+0x1a/0x74 [nilfs2] but task is already holding lock: (&bmap->b_sem){++++-.}, at: [<e0d024e0>] nilfs_bmap_truncate+0x19/0x6a [nilfs2] other info that might help us debug this: 2 locks held by nilfs_cleanerd/10607: #0: (&nilfs->ns_segctor_sem){++++.+}, at: [<e0d0d75a>] nilfs_transaction_begin+0xb6/0x10c [nilfs2] #1: (&bmap->b_sem){++++-.}, at: [<e0d024e0>] nilfs_bmap_truncate+0x19/0x6a [nilfs2] Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> --- fs/nilfs2/bmap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 36df60b6d8a4b..99d58a028b94c 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -568,6 +568,7 @@ void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap, } static struct lock_class_key nilfs_bmap_dat_lock_key; +static struct lock_class_key nilfs_bmap_mdt_lock_key; /** * nilfs_bmap_read - read a bmap from an inode @@ -603,7 +604,11 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) bmap->b_ptr_type = NILFS_BMAP_PTR_VS; bmap->b_last_allocated_key = 0; bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); break; + case NILFS_IFILE_INO: + lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); + /* Fall through */ default: bmap->b_ptr_type = NILFS_BMAP_PTR_VM; bmap->b_last_allocated_key = 0; -- GitLab From d9a0a345ab7a58a30ec38e5bb7401a28714914d2 Mon Sep 17 00:00:00 2001 From: Jiro SEKIBA <jir@unicus.jp> Date: Sat, 4 Jul 2009 23:00:53 +0900 Subject: [PATCH 0700/1002] nilfs2: fix disorder in cp count on error during deleting checkpoints This fixes a bug that checkpoint count gets wrong on errors when deleting a series of checkpoints. The count error is persistent since the checkpoint count is stored on disk. Some userland programs refer to the count via ioctl, and this bugfix is needed to prevent malfunction of such programs. Signed-off-by: Jiro SEKIBA <jir@unicus.jp> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: stable@kernel.org --- fs/nilfs2/cpfile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 7d49813f66d6c..aec942cf79e34 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -307,7 +307,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); if (ret < 0) { if (ret != -ENOENT) - goto out_header; + break; /* skip hole */ ret = 0; continue; @@ -340,7 +340,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, continue; printk(KERN_ERR "%s: cannot delete block\n", __func__); - goto out_header; + break; } } @@ -358,7 +358,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, kunmap_atomic(kaddr, KM_USER0); } - out_header: brelse(header_bh); out_sem: -- GitLab From 91b4eaea93f5be95f4477554399680a53aff2343 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Sun, 5 Jul 2009 07:39:17 +0200 Subject: [PATCH 0701/1002] perf report: Warn on callchain output request from non-callchain file perf report segfaults while trying to handle callchains from a non callchain data file. Instead of a segfault, print a useful message to the user. Reported-by: Jens Axboe <jens.axboe@oracle.com> Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246772361-9960-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index fa937f5c3c395..9f9575afab081 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1684,9 +1684,19 @@ static int __cmd_report(void) sample_type = perf_header__sample_type(); - if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { - fprintf(stderr, "selected --sort parent, but no callchain data\n"); - exit(-1); + if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { + if (sort__has_parent) { + fprintf(stderr, "selected --sort parent, but no" + " callchain data. Did you call" + " perf record without -g?\n"); + exit(-1); + } + if (callchain) { + fprintf(stderr, "selected -c but no callchain data." + " Did you call perf record without" + " -g?\n"); + exit(-1); + } } if (load_kernel() < 0) { -- GitLab From be9038859e56f729cc9d3b070a35fb8829a73696 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Sun, 5 Jul 2009 07:39:18 +0200 Subject: [PATCH 0702/1002] perf report: Use a modifiable string for default callchain options If the user doesn't provide options to tune his callchain output (ie: if he uses -c without arguments) then the default value passed in the OPT_CALLBACK_DEFAULT() macro is used. But it's parsed later by strtok() which will replace comma separators to a zero. This may segfault as we are using a read-only string. Use a modifiable one instead, and also fix the "100%" default minimum threshold value by turning it into a 0 (output every callchains) as it was intended in the origin. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246772361-9960-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 9f9575afab081..3db99fd99867c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -58,6 +58,8 @@ static char *parent_pattern = default_parent_pattern; static regex_t parent_regex; static int exclude_other = 1; + +static char callchain_default_opt[] = "flat,0"; static int callchain; static enum chain_mode callchain_mode; static double callchain_min_percent = 0.0; @@ -1871,7 +1873,7 @@ static const struct option options[] = { "Only display entries with parent-match"), OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent", "Display callchains using output_type and min percent threshold. " - "Default: flat,0", &parse_callchain_opt, "flat,100"), + "Default: flat,0", &parse_callchain_opt, callchain_default_opt), OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", -- GitLab From 94a8eb028a57854157a936c7e66b09e2559f115a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Sun, 5 Jul 2009 07:39:19 +0200 Subject: [PATCH 0703/1002] perf report: Change default callchain parameters The default callchain parameters are set to use the flat mode and never filter any overhead threshold of backtrace. But flat mode is boring compared to graph mode. Also the number of callchains may be very high if none is filtered. Let's change this to set the graph view and a minimum overhead of 0.5% as default parameters. Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246772361-9960-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3db99fd99867c..8bd58651128cf 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -59,10 +59,10 @@ static regex_t parent_regex; static int exclude_other = 1; -static char callchain_default_opt[] = "flat,0"; +static char callchain_default_opt[] = "graph,0.5"; static int callchain; static enum chain_mode callchain_mode; -static double callchain_min_percent = 0.0; +static double callchain_min_percent = 0.5; static u64 sample_type; -- GitLab From e05b876c222178bc6abcfa9f23d8311731691046 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Sun, 5 Jul 2009 07:39:20 +0200 Subject: [PATCH 0704/1002] perf_counter tools: callchains: Manage the cumul hits on the fly The cumul hits are the number of hits of every childs of a node plus the hits of the current nodes, required for percentage computing of a branch. Theses numbers are calculated during the sorting of the branches of the callchain tree using a depth first postfix traversal, so that cumulative hits are propagated in the right order. But if we plan to implement percentages relative to the parent and not absolute percentages (relative to the whole overhead), we need to know the cumulative hits of the parent before computing the children because the relative minimum acceptable number of entries (ie: minimum rate against the cumulative hits from the parent) is the basis to filter the children against a given rate. Then we need to handle the cumul hits on the fly to prepare the implementation of relative overhead rates. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246772361-9960-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/util/callchain.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index c9900fe6b8b41..5d244afb7cdf1 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -74,13 +74,11 @@ static void __sort_chain_graph(struct callchain_node *node, u64 min_hit) struct callchain_node *child; node->rb_root = RB_ROOT; - node->cumul_hit = node->hit; chain_for_each_child(child, node) { __sort_chain_graph(child, min_hit); if (child->cumul_hit >= min_hit) rb_insert_callchain(&node->rb_root, child, GRAPH); - node->cumul_hit += child->cumul_hit; } } @@ -159,7 +157,7 @@ add_child(struct callchain_node *parent, struct ip_callchain *chain, new = create_child(parent, false); fill_node(new, chain, start, syms); - new->hit = 1; + new->cumul_hit = new->hit = 1; } /* @@ -189,6 +187,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, /* split the hits */ new->hit = parent->hit; + new->cumul_hit = parent->cumul_hit; new->val_nr = parent->val_nr - idx_local; parent->val_nr = idx_local; @@ -216,10 +215,13 @@ __append_chain_children(struct callchain_node *root, struct ip_callchain *chain, unsigned int ret = __append_chain(rnode, chain, start, syms); if (!ret) - return; + goto cumul; } /* nothing in children, add to the current node */ add_child(root, chain, start, syms); + +cumul: + root->cumul_hit++; } static int @@ -261,6 +263,8 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, /* we match 100% of the path, increment the hit */ if (i - start == root->val_nr && i == chain->nr) { root->hit++; + root->cumul_hit++; + return 0; } -- GitLab From 805d127d62472f17c7d79baa001a7651afe2fa47 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker <fweisbec@gmail.com> Date: Sun, 5 Jul 2009 07:39:21 +0200 Subject: [PATCH 0705/1002] perf report: Add "Fractal" mode output - support callchains with relative overhead rate The current callchain displays the overhead rates as absolute: relative to the total overhead. This patch provides relative overhead percentage, in which each branch of the callchain tree is a independant instrumentated object. This provides a 'fractal' view of the call-chain profile: each sub-graph looks like a profile in itself - relative to its parent. You can produce such output by using the "fractal" mode that you can abbreviate via f, fr, fra, frac, etc... ./perf report -s sym -c fractal Example: 8.46% [k] copy_user_generic_string | |--52.01%-- generic_file_aio_read | do_sync_read | vfs_read | | | |--97.20%-- sys_pread64 | | system_call_fastpath | | pread64 | | | --2.81%-- sys_read | system_call_fastpath | __read | |--39.85%-- generic_file_buffered_write | __generic_file_aio_write_nolock | generic_file_aio_write | do_sync_write | reiserfs_file_write | vfs_write | | | |--97.05%-- sys_pwrite64 | | system_call_fastpath | | __pwrite64 | | | --2.95%-- sys_write | system_call_fastpath | __write_nocancel [...] Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Jens Axboe <jens.axboe@oracle.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1246772361-9960-5-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- tools/perf/builtin-report.c | 60 +++++++++++++++++--------- tools/perf/util/callchain.c | 84 ++++++++++++++++++++++++++++++------- tools/perf/util/callchain.h | 21 +++++++--- 3 files changed, 124 insertions(+), 41 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8bd58651128cf..4e5cc266311e1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -59,10 +59,15 @@ static regex_t parent_regex; static int exclude_other = 1; -static char callchain_default_opt[] = "graph,0.5"; +static char callchain_default_opt[] = "fractal,0.5"; + static int callchain; -static enum chain_mode callchain_mode; -static double callchain_min_percent = 0.5; + +static +struct callchain_param callchain_param = { + .mode = CHAIN_GRAPH_ABS, + .min_percent = 0.5 +}; static u64 sample_type; @@ -846,9 +851,15 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, struct callchain_node *child; struct callchain_list *chain; int new_depth_mask = depth_mask; + u64 new_total; size_t ret = 0; int i; + if (callchain_param.mode == CHAIN_GRAPH_REL) + new_total = self->cumul_hit; + else + new_total = total_samples; + node = rb_first(&self->rb_root); while (node) { child = rb_entry(node, struct callchain_node, rb_node); @@ -873,10 +884,10 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, continue; ret += ipchain__fprintf_graph(fp, chain, depth, new_depth_mask, i++, - total_samples, + new_total, child->cumul_hit); } - ret += callchain__fprintf_graph(fp, child, total_samples, + ret += callchain__fprintf_graph(fp, child, new_total, depth + 1, new_depth_mask | (1 << depth)); node = next; @@ -925,13 +936,18 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; - if (callchain_mode == FLAT) { + switch (callchain_param.mode) { + case CHAIN_FLAT: ret += percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += callchain__fprintf_flat(fp, chain, total_samples); - } else if (callchain_mode == GRAPH) { + break; + case CHAIN_GRAPH_ABS: /* Falldown */ + case CHAIN_GRAPH_REL: ret += callchain__fprintf_graph(fp, chain, total_samples, 1, 1); + default: + break; } ret += fprintf(fp, "\n"); rb_node = rb_next(rb_node); @@ -1219,14 +1235,9 @@ static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits) struct rb_node *parent = NULL; struct hist_entry *iter; - if (callchain) { - if (callchain_mode == FLAT) - sort_chain_flat(&he->sorted_chain, &he->callchain, - min_callchain_hits); - else if (callchain_mode == GRAPH) - sort_chain_graph(&he->sorted_chain, &he->callchain, - min_callchain_hits); - } + if (callchain) + callchain_param.sort(&he->sorted_chain, &he->callchain, + min_callchain_hits, &callchain_param); while (*p != NULL) { parent = *p; @@ -1249,7 +1260,7 @@ static void output__resort(u64 total_samples) struct rb_root *tree = &hist; u64 min_callchain_hits; - min_callchain_hits = total_samples * (callchain_min_percent / 100); + min_callchain_hits = total_samples * (callchain_param.min_percent / 100); if (sort__need_collapse) tree = &collapse_hists; @@ -1829,22 +1840,31 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, /* get the output mode */ if (!strncmp(tok, "graph", strlen(arg))) - callchain_mode = GRAPH; + callchain_param.mode = CHAIN_GRAPH_ABS; else if (!strncmp(tok, "flat", strlen(arg))) - callchain_mode = FLAT; + callchain_param.mode = CHAIN_FLAT; + + else if (!strncmp(tok, "fractal", strlen(arg))) + callchain_param.mode = CHAIN_GRAPH_REL; + else return -1; /* get the min percentage */ tok = strtok(NULL, ","); if (!tok) - return 0; + goto setup; - callchain_min_percent = strtod(tok, &endptr); + callchain_param.min_percent = strtod(tok, &endptr); if (tok == endptr) return -1; +setup: + if (register_callchain_param(&callchain_param) < 0) { + fprintf(stderr, "Can't register callchain params\n"); + return -1; + } return 0; } diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 5d244afb7cdf1..9d3c8141b8c15 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -32,13 +32,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, rnode = rb_entry(parent, struct callchain_node, rb_node); switch (mode) { - case FLAT: + case CHAIN_FLAT: if (rnode->hit < chain->hit) p = &(*p)->rb_left; else p = &(*p)->rb_right; break; - case GRAPH: + case CHAIN_GRAPH_ABS: /* Falldown */ + case CHAIN_GRAPH_REL: if (rnode->cumul_hit < chain->cumul_hit) p = &(*p)->rb_left; else @@ -53,43 +54,96 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, rb_insert_color(&chain->rb_node, root); } +static void +__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit) +{ + struct callchain_node *child; + + chain_for_each_child(child, node) + __sort_chain_flat(rb_root, child, min_hit); + + if (node->hit && node->hit >= min_hit) + rb_insert_callchain(rb_root, node, CHAIN_FLAT); +} + /* * Once we get every callchains from the stream, we can now * sort them by hit */ -void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, - u64 min_hit) +static void +sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, + u64 min_hit, struct callchain_param *param __used) +{ + __sort_chain_flat(rb_root, node, min_hit); +} + +static void __sort_chain_graph_abs(struct callchain_node *node, + u64 min_hit) { struct callchain_node *child; - chain_for_each_child(child, node) - sort_chain_flat(rb_root, child, min_hit); + node->rb_root = RB_ROOT; - if (node->hit && node->hit >= min_hit) - rb_insert_callchain(rb_root, node, FLAT); + chain_for_each_child(child, node) { + __sort_chain_graph_abs(child, min_hit); + if (child->cumul_hit >= min_hit) + rb_insert_callchain(&node->rb_root, child, + CHAIN_GRAPH_ABS); + } +} + +static void +sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root, + u64 min_hit, struct callchain_param *param __used) +{ + __sort_chain_graph_abs(chain_root, min_hit); + rb_root->rb_node = chain_root->rb_root.rb_node; } -static void __sort_chain_graph(struct callchain_node *node, u64 min_hit) +static void __sort_chain_graph_rel(struct callchain_node *node, + double min_percent) { struct callchain_node *child; + u64 min_hit; node->rb_root = RB_ROOT; + min_hit = node->cumul_hit * min_percent / 100.0; chain_for_each_child(child, node) { - __sort_chain_graph(child, min_hit); + __sort_chain_graph_rel(child, min_percent); if (child->cumul_hit >= min_hit) - rb_insert_callchain(&node->rb_root, child, GRAPH); + rb_insert_callchain(&node->rb_root, child, + CHAIN_GRAPH_REL); } } -void -sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root, - u64 min_hit) +static void +sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root, + u64 min_hit __used, struct callchain_param *param) { - __sort_chain_graph(chain_root, min_hit); + __sort_chain_graph_rel(chain_root, param->min_percent); rb_root->rb_node = chain_root->rb_root.rb_node; } +int register_callchain_param(struct callchain_param *param) +{ + switch (param->mode) { + case CHAIN_GRAPH_ABS: + param->sort = sort_chain_graph_abs; + break; + case CHAIN_GRAPH_REL: + param->sort = sort_chain_graph_rel; + break; + case CHAIN_FLAT: + param->sort = sort_chain_flat; + break; + default: + return -1; + } + return 0; +} + /* * Create a child for a parent. If inherit_children, then the new child * will become the new parent of it's parent children diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index f3e4776e74300..7812122bea1d5 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -7,8 +7,9 @@ #include "symbol.h" enum chain_mode { - FLAT, - GRAPH + CHAIN_FLAT, + CHAIN_GRAPH_ABS, + CHAIN_GRAPH_REL }; struct callchain_node { @@ -23,6 +24,17 @@ struct callchain_node { u64 cumul_hit; /* hit + hits of children */ }; +struct callchain_param; + +typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, + u64, struct callchain_param *); + +struct callchain_param { + enum chain_mode mode; + double min_percent; + sort_chain_func_t sort; +}; + struct callchain_list { u64 ip; struct symbol *sym; @@ -36,10 +48,7 @@ static inline void callchain_init(struct callchain_node *node) INIT_LIST_HEAD(&node->val); } +int register_callchain_param(struct callchain_param *param); void append_chain(struct callchain_node *root, struct ip_callchain *chain, struct symbol **syms); -void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, - u64 min_hit); -void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node, - u64 min_hit); #endif -- GitLab From aba6653617754e12763a0d3c9dda332b66190a50 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Sun, 5 Jul 2009 11:44:46 +0200 Subject: [PATCH 0706/1002] ALSA: hda - Fix error path in the sanity check in azx_pcm_open() Release resources cleanly after errors in the sanity check in azx_pcm_open(). Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_intel.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1877d95d4aa67..16e09d7405729 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1455,6 +1455,17 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) return err; } snd_pcm_limit_hw_rates(runtime); + /* sanity check */ + if (snd_BUG_ON(!runtime->hw.channels_min) || + snd_BUG_ON(!runtime->hw.channels_max) || + snd_BUG_ON(!runtime->hw.formats) || + snd_BUG_ON(!runtime->hw.rates)) { + azx_release_device(azx_dev); + hinfo->ops.close(hinfo, apcm->codec, substream); + snd_hda_power_down(apcm->codec); + mutex_unlock(&chip->open_mutex); + return -EINVAL; + } spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = substream; azx_dev->running = 0; @@ -1463,13 +1474,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) runtime->private_data = azx_dev; snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); - - if (snd_BUG_ON(!runtime->hw.channels_min || !runtime->hw.channels_max)) - return -EINVAL; - if (snd_BUG_ON(!runtime->hw.formats)) - return -EINVAL; - if (snd_BUG_ON(!runtime->hw.rates)) - return -EINVAL; return 0; } -- GitLab From c285addb3991c9b73b8d1a2b652ce0f1f67e90e1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Thu, 25 Jun 2009 16:28:23 -0300 Subject: [PATCH 0707/1002] V4L/DVB (12134): vivi: bug: don't assume that S_STD will be called before streaming precalculate_bars() improved vivi performance. However, it assumed that always before streaming, the driver would call VIDIOC_S_STD. This is not an API requirement, and the testing apps don't do that. Due to that, a regression were caused by the patch that added it. This patch moves the precalculate_bars to the proper place of the code, calling it at buffer_prepare() callback. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/vivi.c | 99 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index cd72668584626..7705fc6baf00d 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -343,6 +343,53 @@ static struct bar_std bars[] = { #define TO_U(r, g, b) \ (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) +/* precalculate color bar values to speed up rendering */ +static void precalculate_bars(struct vivi_fh *fh) +{ + struct vivi_dev *dev = fh->dev; + unsigned char r, g, b; + int k, is_yuv; + + fh->input = dev->input; + + for (k = 0; k < 8; k++) { + r = bars[fh->input].bar[k][0]; + g = bars[fh->input].bar[k][1]; + b = bars[fh->input].bar[k][2]; + is_yuv = 0; + + switch (fh->fmt->fourcc) { + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + is_yuv = 1; + break; + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + r >>= 3; + g >>= 2; + b >>= 3; + break; + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_RGB555X: + r >>= 3; + g >>= 3; + b >>= 3; + break; + } + + if (is_yuv) { + fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ + fh->bars[k][1] = TO_U(r, g, b); /* Cb */ + fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + } else { + fh->bars[k][0] = r; + fh->bars[k][1] = g; + fh->bars[k][2] = b; + } + } + +} + #define TSTAMP_MIN_Y 24 #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) #define TSTAMP_INPUT_X 10 @@ -755,6 +802,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.height = fh->height; buf->vb.field = field; + precalculate_bars(fh); + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) @@ -893,53 +942,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -/* precalculate color bar values to speed up rendering */ -static void precalculate_bars(struct vivi_fh *fh) -{ - struct vivi_dev *dev = fh->dev; - unsigned char r, g, b; - int k, is_yuv; - - fh->input = dev->input; - - for (k = 0; k < 8; k++) { - r = bars[fh->input].bar[k][0]; - g = bars[fh->input].bar[k][1]; - b = bars[fh->input].bar[k][2]; - is_yuv = 0; - - switch (fh->fmt->fourcc) { - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - is_yuv = 1; - break; - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - r >>= 3; - g >>= 2; - b >>= 3; - break; - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - r >>= 3; - g >>= 3; - b >>= 3; - break; - } - - if (is_yuv) { - fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ - fh->bars[k][1] = TO_U(r, g, b); /* Cb */ - fh->bars[k][2] = TO_V(r, g, b); /* Cr */ - } else { - fh->bars[k][0] = r; - fh->bars[k][1] = g; - fh->bars[k][2] = b; - } - } - -} - /*FIXME: This seems to be generic enough to be at videodev2 */ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) @@ -965,8 +967,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vb_vidq.field = f->fmt.pix.field; fh->type = f->type; - precalculate_bars(fh); - ret = 0; out: mutex_unlock(&q->vb_lock); @@ -1357,6 +1357,7 @@ static int __init vivi_create_instance(int inst) goto unreg_dev; *vfd = vivi_template; + vfd->debug = debug; ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); if (ret < 0) -- GitLab From 7c3a742a86055df1d18aac25bb8652735b3491ef Mon Sep 17 00:00:00 2001 From: Sean MacLennan <smaclennan@pikatech.com> Date: Tue, 16 Jun 2009 05:24:35 +0000 Subject: [PATCH 0708/1002] powerpc/44x: Update Warp defconfig * Enable GPIO LEDS and LED triggers * Move to SLUB * Enable HOTPLUG * Enable timestamps on printks * Enable UBIFS * Enable in-kernel config Signed-off-by: Sean MacLennan <smaclennan@pikatech.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> --- arch/powerpc/configs/44x/warp_defconfig | 200 +++++++++++++++++++----- 1 file changed, 157 insertions(+), 43 deletions(-) diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig index 3b77f092abe12..787635f23d8fd 100644 --- a/arch/powerpc/configs/44x/warp_defconfig +++ b/arch/powerpc/configs/44x/warp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.29-rc2 -# Fri Jan 23 07:57:16 2009 +# Linux kernel version: 2.6.30 +# Tue Jun 9 23:35:36 2009 # # CONFIG_PPC64 is not set @@ -41,6 +41,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_NO_VIRT_TO_BUS is not set CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -53,10 +54,12 @@ CONFIG_PPC_UDBG_16550=y # CONFIG_GENERIC_TBSYNC is not set CONFIG_AUDIT_ARCH=y CONFIG_GENERIC_BUG=y +CONFIG_DTC=y # CONFIG_DEFAULT_UIMAGE is not set CONFIG_PPC_DCR_NATIVE=y # CONFIG_PPC_DCR_MMIO is not set CONFIG_PPC_DCR=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -74,7 +77,17 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y @@ -82,27 +95,29 @@ CONFIG_FAIR_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_HOTPLUG is not set +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y -CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y @@ -110,10 +125,13 @@ CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y @@ -121,6 +139,7 @@ CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_SLOW_WORK is not set # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -133,7 +152,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y # CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -149,11 +167,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y -# CONFIG_TREE_RCU is not set -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_FREEZER is not set # @@ -173,10 +186,11 @@ CONFIG_WARP=y # CONFIG_ARCHES is not set # CONFIG_CANYONLANDS is not set # CONFIG_GLACIER is not set +# CONFIG_REDWOOD is not set # CONFIG_YOSEMITE is not set # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set # CONFIG_PPC44x_SIMPLE is not set -# CONFIG_PPC4xx_GPIO is not set +CONFIG_PPC4xx_GPIO=y CONFIG_440EP=y CONFIG_IBM440EP_ERR42=y # CONFIG_IPIC is not set @@ -235,9 +249,13 @@ CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_STDBINUTILS=y CONFIG_PPC_4K_PAGES=y # CONFIG_PPC_16K_PAGES is not set # CONFIG_PPC_64K_PAGES is not set +# CONFIG_PPC_256K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y CONFIG_CMDLINE_BOOL=y @@ -256,6 +274,7 @@ CONFIG_PPC_PCI_CHOICE=y # CONFIG_PCI_DOMAINS is not set # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set # CONFIG_HAS_RAPIDIO is not set # @@ -271,14 +290,12 @@ CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_KERNEL_START=0xc0000000 CONFIG_PHYSICAL_START=0x00000000 CONFIG_TASK_SIZE=0xc0000000 -CONFIG_CONSISTENT_START=0xff100000 CONFIG_CONSISTENT_SIZE=0x00200000 CONFIG_NET=y # # Networking options # -CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -353,6 +370,7 @@ CONFIG_VLAN_8021Q=y # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -365,7 +383,6 @@ CONFIG_VLAN_8021Q=y # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set -# CONFIG_PHONET is not set # CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set @@ -378,8 +395,12 @@ CONFIG_VLAN_8021Q=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -471,13 +492,21 @@ CONFIG_MTD_NAND_NDFC=y # LPDDR flash memory drivers # # CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_QINFO_PROBE is not set # # UBI - Unsorted block images # -# CONFIG_MTD_UBI is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y CONFIG_OF_I2C=y # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y @@ -495,10 +524,17 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_XILINX_SYSACE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y -# CONFIG_EEPROM_93CX6 is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set # CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -529,7 +565,7 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCSI_WAIT_SCAN is not set # # SCSI Transports @@ -541,10 +577,12 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set # CONFIG_ATA is not set # CONFIG_MD is not set # CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -554,6 +592,8 @@ CONFIG_NETDEVICES=y # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_ETHOC is not set +# CONFIG_DNET is not set CONFIG_IBM_NEW_EMAC=y CONFIG_IBM_NEW_EMAC_RXB=128 CONFIG_IBM_NEW_EMAC_TXB=64 @@ -577,7 +617,6 @@ CONFIG_IBM_NEW_EMAC_ZMII=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -646,6 +685,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_NVRAM is not set # CONFIG_GEN_RTC is not set # CONFIG_R3964 is not set @@ -663,6 +703,7 @@ CONFIG_I2C_HELPER_AUTO=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_GPIO is not set CONFIG_I2C_IBM_IIC=y # CONFIG_I2C_MPC is not set # CONFIG_I2C_OCORES is not set @@ -685,12 +726,9 @@ CONFIG_I2C_IBM_IIC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_LEGACY=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -699,7 +737,30 @@ CONFIG_EEPROM_LEGACY=y # CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -# CONFIG_GPIOLIB is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_XILINX is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y @@ -721,6 +782,7 @@ CONFIG_SENSORS_AD7414=y # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set @@ -735,11 +797,15 @@ CONFIG_SENSORS_AD7414=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set @@ -785,6 +851,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set @@ -870,11 +937,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # -# see USB_STORAGE Help for more information +# also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -915,7 +982,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set @@ -929,6 +995,8 @@ CONFIG_USB_STORAGE=y # # OTG and related infrastructure # +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set @@ -946,6 +1014,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y # # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_WBSD is not set +CONFIG_MMC_PIKASD=y # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -953,16 +1022,31 @@ CONFIG_LEDS_CLASS=y # # LED drivers # +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_GPIO_PLATFORM is not set +CONFIG_LEDS_GPIO_OF=y +# CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set # # LED Triggers # -# CONFIG_LEDS_TRIGGERS is not set +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# # CONFIG_ACCESSIBILITY is not set # CONFIG_EDAC is not set # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set @@ -973,6 +1057,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set # CONFIG_EXT4_FS is not set CONFIG_JBD=y @@ -992,6 +1077,11 @@ CONFIG_INOTIFY_USER=y # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set +# +# Caches +# +# CONFIG_FSCACHE is not set + # # CD-ROM/DVD Filesystems # @@ -1039,6 +1129,12 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_XATTR is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1049,6 +1145,7 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1060,7 +1157,6 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1115,6 +1211,7 @@ CONFIG_NLS_ISO8859_15=y # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y # CONFIG_DLM is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines @@ -1122,7 +1219,7 @@ CONFIG_NLS_UTF8=y CONFIG_BITREVERSE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y -# CONFIG_CRC16 is not set +CONFIG_CRC16=y CONFIG_CRC_T10DIF=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y @@ -1130,16 +1227,19 @@ CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_HAVE_LMB=y +CONFIG_NLATTR=y # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set +CONFIG_PRINTK_TIME=y CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 @@ -1152,11 +1252,15 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1180,9 +1284,12 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y # # Tracers @@ -1190,24 +1297,27 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # CONFIG_FUNCTION_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set # CONFIG_BOOT_TRACER is not set # CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set -# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_CODE_PATCHING_SELFTEST is not set # CONFIG_FTR_FIXUP_SELFTEST is not set # CONFIG_MSI_BITMAP_SELFTEST is not set # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_VIRQ_DEBUG is not set -CONFIG_BDI_SWITCH=y +# CONFIG_BDI_SWITCH is not set # CONFIG_PPC_EARLY_DEBUG is not set # @@ -1223,6 +1333,8 @@ CONFIG_CRYPTO=y # Crypto core or helper # # CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y # CONFIG_CRYPTO_MANAGER is not set # CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set @@ -1294,13 +1406,15 @@ CONFIG_CRYPTO=y # # Compression # -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y # # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_PPC4XX is not set # CONFIG_PPC_CLOCK is not set # CONFIG_VIRTUALIZATION is not set -- GitLab From ba703e1a7a0b32f740bcfba8e60ad193afa4e723 Mon Sep 17 00:00:00 2001 From: Sean MacLennan <smaclennan@pikatech.com> Date: Sun, 28 Jun 2009 11:22:51 +0000 Subject: [PATCH 0709/1002] powerpc/4xx: Have Warp take advantage of GPIO LEDs default-state = keep The GPIO LEDS driver now has a default state of "keep". Update the Warp DTS and platform file to take advantage of this new state. This removes the hardcoding of the two LEDs on the Warp. Signed-off-by: Sean MacLennan <smaclennan@pikatech.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> --- arch/powerpc/boot/dts/warp.dts | 3 ++- arch/powerpc/platforms/44x/warp.c | 16 ++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index 01bfb56bbe802..31605ee4afb69 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts @@ -261,10 +261,11 @@ power-leds { compatible = "gpio-leds"; green { gpios = <&GPIO1 0 0>; - default-state = "on"; + default-state = "keep"; }; red { gpios = <&GPIO1 1 0>; + default-state = "keep"; }; }; diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 0362c88f47d72..9916b391971e1 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -64,8 +64,6 @@ define_machine(warp) { }; -static u32 post_info; - static int __init warp_post_info(void) { struct device_node *np; @@ -87,10 +85,9 @@ static int __init warp_post_info(void) iounmap(fpga); - if (post1 || post2) { + if (post1 || post2) printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2); - post_info = 1; - } else + else printk(KERN_INFO "Warp POST OK\n"); return 0; @@ -179,15 +176,10 @@ static int pika_setup_leds(void) } for_each_child_of_node(np, child) - if (strcmp(child->name, "green") == 0) { + if (strcmp(child->name, "green") == 0) green_led = of_get_gpio(child, 0); - /* Turn back on the green LED */ - gpio_set_value(green_led, 1); - } else if (strcmp(child->name, "red") == 0) { + else if (strcmp(child->name, "red") == 0) red_led = of_get_gpio(child, 0); - /* Set based on post */ - gpio_set_value(red_led, post_info); - } of_node_put(np); -- GitLab From a22ebd069d5b533392e9bef77b73147a2f82b30b Mon Sep 17 00:00:00 2001 From: Josh Boyer <jwboyer@linux.vnet.ibm.com> Date: Sun, 5 Jul 2009 10:02:15 -0400 Subject: [PATCH 0710/1002] powerpc/44x: Fix build error with -Werror for Warp platform With -Werror enabled during the build, the warp.c file fails to build due to the temp_isr function not containing a return statement. This fixes the build error and documents that the function never returns. Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> --- arch/powerpc/platforms/44x/warp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 9916b391971e1..e5c1b096c3e12 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -163,6 +163,9 @@ static irqreturn_t temp_isr(int irq, void *context) value ^= 1; mdelay(500); } + + /* Not reached */ + return IRQ_HANDLED; } static int pika_setup_leds(void) -- GitLab From ba9b42e4ff5eb68f9c946378229d7e45299d7151 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sun, 5 Jul 2009 10:50:37 +0100 Subject: [PATCH 0711/1002] [ARM] export __cpu_flush_dcache_page Now required for libsas: Kernel: arch/arm/boot/Image is ready Kernel: arch/arm/boot/zImage is ready Building modules, stage 2. MODPOST 1096 modules ERROR: "xscale_flush_kern_dcache_page" [drivers/scsi/libsas/libsas.ko] undefined! Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mm/proc-syms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index 195e48edd8c2c..ac5c80062b704 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all); EXPORT_SYMBOL(__cpuc_flush_user_all); EXPORT_SYMBOL(__cpuc_flush_user_range); EXPORT_SYMBOL(__cpuc_coherent_kern_range); +EXPORT_SYMBOL(__cpuc_flush_dcache_page); EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */ #else EXPORT_SYMBOL(cpu_cache); -- GitLab From fb93a1c75eb646fde35985e9af23da936775ae52 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sun, 5 Jul 2009 11:30:15 +0100 Subject: [PATCH 0712/1002] [ARM] pgtable: swp pte layout documentation, definitions, and check Document the layout of our swp PTE entries, adding definitions for the bit masks/shifts/sizes, and implement MAX_SWAPFILES_CHECK() such that we fail to build if we are unable to properly encode the swp type field. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/pgtable.h | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 1cd2d6416bda4..c1d97938f3e21 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -384,16 +384,36 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -/* Encode and decode a swap entry. +/* + * Encode and decode a swap entry. Swap entries are stored in the Linux + * page tables as follows: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * <--------------- offset --------------------> <--- type --> 0 0 * - * We support up to 32GB of swap on 4k machines + * This gives us up to 127 swap files and 32GB per swap file. Note that + * the offset field is always non-zero. */ -#define __swp_type(x) (((x).val >> 2) & 0x7f) -#define __swp_offset(x) ((x).val >> 9) -#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) +#define __SWP_TYPE_SHIFT 2 +#define __SWP_TYPE_BITS 7 +#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) +#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) + +#define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) +#define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) + #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) +/* + * It is an error for the kernel to have more swap files than we can + * encode in the PTEs. This ensures that we know when MAX_SWAPFILES + * is increased beyond what we presently support. + */ +#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) + /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ #define kern_addr_valid(addr) (1) -- GitLab From 65b1bfc13e8f50034187e339aa12b81cd6785bd5 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sun, 5 Jul 2009 11:52:21 +0100 Subject: [PATCH 0713/1002] [ARM] pgtable: file pte layout documentation Document the layout of our file PTE entries. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/pgtable.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index c1d97938f3e21..c433c6c73112a 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -285,15 +285,6 @@ extern struct page *empty_zero_page; #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) #define pte_special(pte) (0) -/* - * The following only works if pte_present() is not true. - */ -#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) -#define pte_to_pgoff(x) (pte_val(x) >> 2) -#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) - -#define PTE_FILE_MAX_BITS 30 - #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -414,6 +405,20 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; */ #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) +/* + * Encode and decode a file entry. File entries are stored in the Linux + * page tables as follows: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * <------------------------ offset -------------------------> 1 0 + */ +#define pte_file(pte) (pte_val(pte) & L_PTE_FILE) +#define pte_to_pgoff(x) (pte_val(x) >> 2) +#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) + +#define PTE_FILE_MAX_BITS 30 + /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ #define kern_addr_valid(addr) (1) -- GitLab From e3dc5a665d39112e98cfd5bbc7fda2963c00c12c Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Mon, 22 Jun 2009 17:31:09 +0300 Subject: [PATCH 0714/1002] UBIFS: fix integer overflow warning Fix the following warning: fs/ubifs/io.c: In function 'ubifs_wbuf_init': fs/ubifs/io.c:860: warning: integer overflow in expression And limit maximum hrtimer delta to ULONG_MAX because the argument is 'unsigned long'. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index bc5857199ec2a..2d41ae1d66073 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -857,7 +857,9 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) * and hard limits. */ hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0); - wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10; + wbuf->delta = DEFAULT_WBUF_TIMEOUT_SECS * 1000000000ULL * 2 / 10; + if (wbuf->delta > ULONG_MAX) + wbuf->delta = ULONG_MAX; wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta); hrtimer_set_expires_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta); -- GitLab From 70aee2f153972f70fad5f7025134fec063f9efbe Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Thu, 18 Jun 2009 13:37:15 +0300 Subject: [PATCH 0715/1002] UBIFS: improve debugging messaged 1. Make the I/O debugging message print the journal head number. 2. Add prints to timer functions. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/io.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 2d41ae1d66073..2ef689a9a363b 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -297,6 +297,7 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer) { struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer); + dbg_io("jhead %d", wbuf->jhead); wbuf->need_sync = 1; wbuf->c->need_wbuf_sync = 1; ubifs_wake_up_bgt(wbuf->c); @@ -313,6 +314,9 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) if (!ktime_to_ns(wbuf->softlimit)) return; + dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead, + ktime_to_ns(wbuf->softlimit)/USEC_PER_SEC, + (ktime_to_ns(wbuf->softlimit) + wbuf->delta)/USEC_PER_SEC); hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta, HRTIMER_MODE_REL); } @@ -349,8 +353,8 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) /* Write-buffer is empty or not seeked */ return 0; - dbg_io("LEB %d:%d, %d bytes", - wbuf->lnum, wbuf->offs, wbuf->used); + dbg_io("LEB %d:%d, %d bytes, jhead %d", + wbuf->lnum, wbuf->offs, wbuf->used, wbuf->jhead); ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); ubifs_assert(!(wbuf->avail & 7)); ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); @@ -399,7 +403,7 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, { const struct ubifs_info *c = wbuf->c; - dbg_io("LEB %d:%d", lnum, offs); + dbg_io("LEB %d:%d, jhead %d", lnum, offs, wbuf->jhead); ubifs_assert(lnum >= 0 && lnum < c->leb_cnt); ubifs_assert(offs >= 0 && offs <= c->leb_size); ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7)); @@ -506,9 +510,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) struct ubifs_info *c = wbuf->c; int err, written, n, aligned_len = ALIGN(len, 8), offs; - dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len, - dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum, - wbuf->offs + wbuf->used); + dbg_io("%d bytes (%s) to jhead %d wbuf at LEB %d:%d", len, + dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->jhead, + wbuf->lnum, wbuf->offs + wbuf->used); ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt); ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0); ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); @@ -533,8 +537,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) memcpy(wbuf->buf + wbuf->used, buf, len); if (aligned_len == wbuf->avail) { - dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, - wbuf->offs); + dbg_io("flush jhead %d wbuf to LEB %d:%d", + wbuf->jhead, wbuf->lnum, wbuf->offs); err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, c->min_io_size, wbuf->dtype); @@ -562,7 +566,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) * minimal I/O unit. We have to fill and flush write-buffer and switch * to the next min. I/O unit. */ - dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs); + dbg_io("flush jhead %d wbuf to LEB %d:%d", + wbuf->jhead, wbuf->lnum, wbuf->offs); memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, c->min_io_size, wbuf->dtype); @@ -695,7 +700,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, int err, rlen, overlap; struct ubifs_ch *ch = buf; - dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); + dbg_io("LEB %d:%d, %s, length %d, jhead %d", lnum, offs, + dbg_ntype(type), len, wbuf->jhead); ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0); ubifs_assert(!(offs & 7) && offs < c->leb_size); ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); -- GitLab From 0b335b9d7d5f0b832e90ac469480789c07be80ad Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Tue, 23 Jun 2009 12:30:43 +0300 Subject: [PATCH 0716/1002] UBIFS: slightly optimize write-buffer timer usage This patch adds the following minor optimization: 1. If write-buffer does not use the timer, indicate it with the wbuf->no_timer variable, instead of using the wbuf->softlimit variable. This is better because wbuf->softlimit is of ktime_t type, and the ktime_to_ns function contains 64-bit multiplication. 2. Do not call the 'hrtimer_cancel()' function for write-buffers which do not use timers. 3. Do not cancel the timer in 'ubifs_put_super()' because the synchronization function does this. This patch also removes a confusing comment. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/io.c | 9 +++------ fs/ubifs/super.c | 6 ++---- fs/ubifs/ubifs.h | 6 ++++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 2ef689a9a363b..9fcf6c38c1bcd 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -312,7 +312,7 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) { ubifs_assert(!hrtimer_active(&wbuf->timer)); - if (!ktime_to_ns(wbuf->softlimit)) + if (wbuf->no_timer) return; dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead, ktime_to_ns(wbuf->softlimit)/USEC_PER_SEC, @@ -327,11 +327,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) */ static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) { - /* - * If the syncer is waiting for the lock (from the background thread's - * context) and another task is changing write-buffer then the syncing - * should be canceled. - */ + if (wbuf->no_timer) + return; wbuf->need_sync = 0; hrtimer_cancel(&wbuf->timer); } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 79fad43f3c57e..5bb272c56a9ba 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -797,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c) * does not need to be synchronized by timer. */ c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; - c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0); + c->jheads[GCHD].wbuf.no_timer = 1; return 0; } @@ -1754,10 +1754,8 @@ static void ubifs_put_super(struct super_block *sb) /* Synchronize write-buffers */ if (c->jheads) - for (i = 0; i < c->jhead_cnt; i++) { + for (i = 0; i < c->jhead_cnt; i++) ubifs_wbuf_sync(&c->jheads[i].wbuf); - hrtimer_cancel(&c->jheads[i].wbuf.timer); - } /* * On fatal errors c->ro_media is set to 1, in which case we do diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 1bf01d8200667..97bc9d09d54bf 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -654,7 +654,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit * and @softlimit + @delta) * @timer: write-buffer timer - * @need_sync: it is set if its timer expired and needs sync + * @no_timer: non-zero if this write-buffer does not timer + * @need_sync: non-zero if its timer expired and needs sync * @next_ino: points to the next position of the following inode number * @inodes: stores the inode numbers of the nodes which are in wbuf * @@ -683,7 +684,8 @@ struct ubifs_wbuf { ktime_t softlimit; unsigned long long delta; struct hrtimer timer; - int need_sync; + unsigned int no_timer:1; + unsigned int need_sync:1; int next_ino; ino_t *inodes; }; -- GitLab From 2a35a3a8ab3e94afd631ed4b45878ceb98f7ab28 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Tue, 23 Jun 2009 20:26:33 +0300 Subject: [PATCH 0717/1002] UBIFS: set write-buffer timout to 3-5 seconds This patch cleans up write-buffer timeout initialization and sets it to 3-5 interval. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/io.c | 17 ++++------------- fs/ubifs/ubifs.h | 5 +++-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 9fcf6c38c1bcd..48d0af94b26a5 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -828,7 +828,6 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) { size_t size; - ktime_t hardlimit; wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); if (!wbuf->buf) @@ -854,18 +853,10 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); wbuf->timer.function = wbuf_timer_callback_nolock; - /* - * Make write-buffer soft limit to be 20% of the hard limit. The - * write-buffer timer is allowed to expire any time between the soft - * and hard limits. - */ - hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0); - wbuf->delta = DEFAULT_WBUF_TIMEOUT_SECS * 1000000000ULL * 2 / 10; - if (wbuf->delta > ULONG_MAX) - wbuf->delta = ULONG_MAX; - wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta); - hrtimer_set_expires_range_ns(&wbuf->timer, wbuf->softlimit, - wbuf->delta); + wbuf->softlimit = ktime_set(WBUF_TIMEOUT_SOFTLIMIT, 0); + wbuf->delta = WBUF_TIMEOUT_HARDLIMIT - WBUF_TIMEOUT_SOFTLIMIT; + wbuf->delta *= 1000000000ULL; + ubifs_assert(wbuf->delta <= ULONG_MAX); return 0; } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 97bc9d09d54bf..c3a707d458a1c 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -95,8 +95,9 @@ */ #define BGT_NAME_PATTERN "ubifs_bgt%d_%d" -/* Default write-buffer synchronization timeout in seconds */ -#define DEFAULT_WBUF_TIMEOUT_SECS 5 +/* Write-buffer synchronization timeout interval in seconds */ +#define WBUF_TIMEOUT_SOFTLIMIT 3 +#define WBUF_TIMEOUT_HARDLIMIT 5 /* Maximum possible inode number (only 32-bit inodes are supported now) */ #define MAX_INUM 0xFFFFFFFF -- GitLab From cb54ef8b1304fe25f3d57031e0f85558a043239f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Tue, 23 Jun 2009 20:30:32 +0300 Subject: [PATCH 0718/1002] UBIFS: few spelling fixes Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/io.c | 6 +++--- fs/ubifs/super.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 48d0af94b26a5..7e4267ecfa567 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -391,7 +391,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) * @offs: logical eraseblock offset to seek to * @dtype: data type * - * This function targets the write buffer to logical eraseblock @lnum:@offs. + * This function targets the write-buffer to logical eraseblock @lnum:@offs. * The write-buffer is synchronized if it is not empty. Returns zero in case of * success and a negative error code in case of failure. */ @@ -822,7 +822,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, * @c: UBIFS file-system description object * @wbuf: write-buffer to initialize * - * This function initializes write buffer. Returns zero in case of success + * This function initializes write-buffer. Returns zero in case of success * %-ENOMEM in case of failure. */ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) @@ -862,7 +862,7 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) /** * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array. - * @wbuf: the write-buffer whereto add + * @wbuf: the write-buffer where to add * @inum: the inode number * * This function adds an inode number to the inode array of the write-buffer. diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 5bb272c56a9ba..76405c457a381 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -986,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, switch (token) { /* * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. - * We accepte them in order to be backware-compatible. But this + * We accept them in order to be backward-compatible. But this * should be removed at some point. */ case Opt_fast_unmount: -- GitLab From 44737589442bf69d811e003d9d0064b8fc1541d6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Wed, 24 Jun 2009 10:15:12 +0300 Subject: [PATCH 0719/1002] UBIFS: fix 64-bit divisions in debug print Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> --- fs/ubifs/io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 7e4267ecfa567..762a7d6cec73d 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -315,8 +315,9 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) if (wbuf->no_timer) return; dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead, - ktime_to_ns(wbuf->softlimit)/USEC_PER_SEC, - (ktime_to_ns(wbuf->softlimit) + wbuf->delta)/USEC_PER_SEC); + div_u64(ktime_to_ns(wbuf->softlimit), USEC_PER_SEC), + div_u64(ktime_to_ns(wbuf->softlimit) + wbuf->delta, + USEC_PER_SEC)); hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta, HRTIMER_MODE_REL); } -- GitLab From 681947d2fa1a00629de33c4df3ca72c39f06a14c Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Wed, 24 Jun 2009 09:59:38 +0300 Subject: [PATCH 0720/1002] UBIFS: minor spelling and grammar fixes Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> --- fs/ubifs/replay.c | 2 +- fs/ubifs/ubifs.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 11cc80125a495..769be42f39d6b 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -957,7 +957,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) return err; out_dump: - ubifs_err("log error detected while replying the log at LEB %d:%d", + ubifs_err("log error detected while replaying the log at LEB %d:%d", lnum, offs + snod->offs); dbg_dump_node(c, snod->node); ubifs_scan_destroy(sleb); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index c3a707d458a1c..a293490944227 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -655,8 +655,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit * and @softlimit + @delta) * @timer: write-buffer timer - * @no_timer: non-zero if this write-buffer does not timer - * @need_sync: non-zero if its timer expired and needs sync + * @no_timer: non-zero if this write-buffer does not have a timer + * @need_sync: non-zero if the timer expired and the wbuf needs sync'ing * @next_ino: points to the next position of the following inode number * @inodes: stores the inode numbers of the nodes which are in wbuf * -- GitLab From 1fb8bd01ed0af0d0577e010e8c6b4234de583fa6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Sun, 28 Jun 2009 18:31:58 +0300 Subject: [PATCH 0721/1002] UBIFS: fix assertion warning When debugging is enabled and an unclean file-system is mounter, the following assertion is triggered: UBIFS assert failed in ubifs_tnc_start_commit at 805 (pid 1081) Call Trace: [cfaffbd0] [c0006cf8] show_stack+0x44/0x16c (unreliable) [cfaffc10] [c011b738] ubifs_tnc_start_commit+0xbb8/0xd18 [cfaffc90] [c0112670] do_commit+0x150/0xa44 [cfaffd10] [c0125234] ubifs_rcvry_gc_commit+0xd8/0x544 [cfaffd60] [c0100e9c] ubifs_fill_super+0xe78/0x15f8 [cfaffdf0] [c0102118] ubifs_get_sb+0x20c/0x320 [cfaffe70] [c007f764] vfs_kern_mount+0x58/0xe0 [cfaffe90] [c007f83c] do_kern_mount+0x40/0xf8 [cfaffeb0] [c0095c24] do_mount+0x550/0x758 [cfafff10] [c0095ebc] sys_mount+0x90/0xe0 [cfafff40] [c000ed4c] ret_from_syscall+0x0/0x3c The reason is that we initialize 'c->min_leb_idx' early, and do not re-calculate it after journal replay. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/super.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 76405c457a381..3507d0ed542d2 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1287,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_journal; + /* Calculate 'min_idx_lebs' after journal replay */ + c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); + err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); if (err) goto out_orphans; -- GitLab From 7fcd9c3ecbf09c0a77db7ba01aac75b32fb79a93 Mon Sep 17 00:00:00 2001 From: Daniel Mack <daniel@caiaq.de> Date: Thu, 2 Jul 2009 17:15:47 +0200 Subject: [PATCH 0722/1002] UBIFS: allow more than one volume to be mounted UBIFS uses a bdi device per volume, but does not care to hand out unique names to each of them. This causes an error when trying to mount more than one volumes. Append the UBI volume and device ID to avoid that. [Amended a bit by Artem Bityutskiy] Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Artem Bityutskiy <dedekind@infradead.org> Cc: Adrian Hunter <ext-adrian.hunter@nokia.com> Cc: linux-mtd@lists.infradead.org Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- fs/ubifs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 3507d0ed542d2..26d2e0d804659 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1976,7 +1976,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) err = bdi_init(&c->bdi); if (err) goto out_close; - err = bdi_register(&c->bdi, NULL, "ubifs"); + err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d", + c->vi.ubi_num, c->vi.vol_id); if (err) goto out_bdi; -- GitLab From 8f6035732a0484a84a1c9cd85312de234ddaa309 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Fri, 3 Jul 2009 11:21:54 +0300 Subject: [PATCH 0723/1002] MAINTAINERS: update ahunter's e-mail address Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 381190c7949ce..20f98b1965364 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5851,7 +5851,7 @@ UBI FILE SYSTEM (UBIFS) P: Artem Bityutskiy M: dedekind@infradead.org P: Adrian Hunter -M: ext-adrian.hunter@nokia.com +M: adrian.hunter@nokia.com L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubifs-2.6.git W: http://www.linux-mtd.infradead.org/doc/ubifs.html -- GitLab From 40a71a87fa8e0cb3ec0fca4d152263734b203eb2 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Sun, 28 Jun 2009 19:16:55 +0300 Subject: [PATCH 0724/1002] UBI: add empty eraseblocks verification This patch adds code which makes sure eraseblocks contain all 0xFF bytes before starting using them. The verification is done only when debugging checks are enabled. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/debug.h | 6 ++++++ drivers/mtd/ubi/io.c | 17 +++++++---------- drivers/mtd/ubi/wl.c | 8 ++++++++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 13777e5beac93..6fc7fda2ab917 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); #define UBI_IO_DEBUG 0 #endif +#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); +#else +#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 +#endif + #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT #define DBG_DISABLE_BGT 1 #else diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index effaff28bab18..6c5441e8791da 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -98,8 +98,6 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_vid_hdr *vid_hdr); -static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, - int len); static int paranoid_check_empty(struct ubi_device *ubi, int pnum); #else #define paranoid_check_not_bad(ubi, pnum) 0 @@ -107,7 +105,6 @@ static int paranoid_check_empty(struct ubi_device *ubi, int pnum); #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 -#define paranoid_check_all_ff(ubi, pnum, offset, len) 0 #define paranoid_check_empty(ubi, pnum) 0 #endif @@ -244,7 +241,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, return err > 0 ? -EINVAL : err; /* The area we are writing to has to contain all 0xFF bytes */ - err = paranoid_check_all_ff(ubi, pnum, offset, len); + err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); if (err) return err > 0 ? -EINVAL : err; @@ -350,7 +347,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) return -EIO; } - err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size); + err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); if (err) return err > 0 ? -EINVAL : err; @@ -672,8 +669,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (read_err != -EBADMSG && check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { /* The physical eraseblock is supposedly empty */ - err = paranoid_check_all_ff(ubi, pnum, 0, - ubi->peb_size); + err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); if (err) return err > 0 ? UBI_IO_BAD_EC_HDR : err; @@ -1229,7 +1225,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) } /** - * paranoid_check_all_ff - check that a region of flash is empty. + * ubi_dbg_check_all_ff - check that a region of flash is empty. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @offset: the starting offset within the physical eraseblock to check @@ -1239,13 +1235,14 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) * @offset of the physical eraseblock @pnum, %1 if not, and a negative error * code if an error occurred. */ -static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, - int len) +int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) { size_t read; int err; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; + ubi_assert(!mutex_is_locked(&ubi->dbg_buf_mutex)); + mutex_lock(&ubi->dbg_buf_mutex); err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); if (err && err != -EUCLEAN) { diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2b2472300610f..e4be446e05ed6 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -459,6 +459,14 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) dbg_wl("PEB %d EC %d", e->pnum, e->ec); prot_queue_add(ubi, e); spin_unlock(&ubi->wl_lock); + + err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, + ubi->peb_size - ubi->vid_hdr_aloffset); + if (err) { + dbg_err("new PEB does not contain all 0xFF bytes"); + return err > 0 ? -EINVAL : err; + } + return e->pnum; } -- GitLab From 1398788fe7b730db10e97dcb9f838603e41922d5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 29 Jun 2009 15:58:36 +0300 Subject: [PATCH 0725/1002] UBI: remove bogus debugging checks The 'paranoid_check_empty()' is bogus because, which is easilly seen on NOR flash, which has long erase cycles, and which may easilly end-up with half-erased eraseblocks. In this case the paranoid check fails. I is just wrong to assume that PEBs which do not have EC headers always contain all 0xFF. Such assumption should not be made on the I/O level, which is quite low. Thus, just kill the check. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/debug.h | 1 + drivers/mtd/ubi/io.c | 87 ----------------------------------------- drivers/mtd/ubi/wl.c | 2 +- 3 files changed, 2 insertions(+), 88 deletions(-) diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 6fc7fda2ab917..a4da7a09b949b 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -173,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void) #define ubi_dbg_is_bitflip() 0 #define ubi_dbg_is_write_failure() 0 #define ubi_dbg_is_erase_failure() 0 +#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 #endif /* !CONFIG_MTD_UBI_DEBUG */ #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 6c5441e8791da..c8edbfd09b64b 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -98,14 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_vid_hdr *vid_hdr); -static int paranoid_check_empty(struct ubi_device *ubi, int pnum); #else #define paranoid_check_not_bad(ubi, pnum) 0 #define paranoid_check_peb_ec_hdr(ubi, pnum) 0 #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 -#define paranoid_check_empty(ubi, pnum) 0 #endif /** @@ -669,10 +667,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (read_err != -EBADMSG && check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { /* The physical eraseblock is supposedly empty */ - err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); - if (err) - return err > 0 ? UBI_IO_BAD_EC_HDR : err; - if (verbose) ubi_warn("no EC header found at PEB %d, " "only 0xFF bytes", pnum); @@ -943,15 +937,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, if (read_err != -EBADMSG && check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { /* The physical eraseblock is supposedly free */ - - /* - * The below is just a paranoid check, it has to be - * compiled out if paranoid checks are disabled. - */ - err = paranoid_check_empty(ubi, pnum); - if (err) - return err > 0 ? UBI_IO_BAD_VID_HDR : err; - if (verbose) ubi_warn("no VID header found at PEB %d, " "only 0xFF bytes", pnum); @@ -1241,8 +1226,6 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) int err; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - ubi_assert(!mutex_is_locked(&ubi->dbg_buf_mutex)); - mutex_lock(&ubi->dbg_buf_mutex); err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); if (err && err != -EUCLEAN) { @@ -1273,74 +1256,4 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) return err; } -/** - * paranoid_check_empty - whether a PEB is empty. - * @ubi: UBI device description object - * @pnum: the physical eraseblock number to check - * - * This function makes sure PEB @pnum is empty, which means it contains only - * %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a - * negative error code in case of failure. - * - * Empty PEBs have the EC header, and do not have the VID header. The caller of - * this function should have already made sure the PEB does not have the VID - * header. However, this function re-checks that, because it is possible that - * the header and data has already been written to the PEB. - * - * Let's consider a possible scenario. Suppose there are 2 tasks - A and B. - * Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to - * find which LEB it corresponds to. PEB X is currently unmapped, and has no - * VID header. Task B is trying to write to PEB X. - * - * Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The - * read data contain all 0xFF bytes; - * Task B: writes VID header and some data to PEB X; - * Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we - * do not re-read the VID header, and do not cancel the checking if it - * is there, we fail. - */ -static int paranoid_check_empty(struct ubi_device *ubi, int pnum) -{ - int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize; - size_t read; - uint32_t magic; - const struct ubi_vid_hdr *vid_hdr; - - mutex_lock(&ubi->dbg_buf_mutex); - err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf); - if (err && err != -EUCLEAN) { - ubi_err("error %d while reading %d bytes from PEB %d:%d, " - "read %zd bytes", err, len, pnum, offs, read); - goto error; - } - - vid_hdr = ubi->dbg_peb_buf; - magic = be32_to_cpu(vid_hdr->magic); - if (magic == UBI_VID_HDR_MAGIC) - /* The PEB contains VID header, so it is not empty */ - goto out; - - err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); - if (err == 0) { - ubi_err("flash region at PEB %d:%d, length %d does not " - "contain all 0xFF bytes", pnum, offs, len); - goto fail; - } - -out: - mutex_unlock(&ubi->dbg_buf_mutex); - return 0; - -fail: - ubi_err("paranoid check failed for PEB %d", pnum); - ubi_msg("hex dump of the %d-%d region", offs, offs + len); - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, - ubi->dbg_peb_buf, len, 1); - err = 1; -error: - ubi_dbg_dump_stack(); - mutex_unlock(&ubi->dbg_buf_mutex); - return err; -} - #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index e4be446e05ed6..600c7229d5cf2 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -463,7 +463,7 @@ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, ubi->peb_size - ubi->vid_hdr_aloffset); if (err) { - dbg_err("new PEB does not contain all 0xFF bytes"); + ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); return err > 0 ? -EINVAL : err; } -- GitLab From 0c6c7fa1313fcb69cae35e34168d2e83b8da854a Mon Sep 17 00:00:00 2001 From: Adrian Hunter <adrian.hunter@nokia.com> Date: Fri, 26 Jun 2009 14:58:01 +0300 Subject: [PATCH 0726/1002] UBI: add image sequence number to EC header An image sequence number is added to the UBI erase-counter header to be able determine if the root file system contains a mixture of old and new images (because the flashing failed to complete). A change to nolo is also needed for this to take effect. Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/build.c | 1 + drivers/mtd/ubi/debug.c | 2 ++ drivers/mtd/ubi/io.c | 15 +++++++++++++-- drivers/mtd/ubi/scan.c | 2 ++ drivers/mtd/ubi/ubi-media.h | 12 +++++++++++- drivers/mtd/ubi/ubi.h | 4 ++++ 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 286ed594e5a0e..db0b9cb64c6ce 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -996,6 +996,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ubi_msg("number of PEBs reserved for bad PEB handling: %d", ubi->beb_rsvd_pebs); ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); + ubi_msg("image sequence number: %d", ubi->image_seq); /* * The below lock makes sure we do not race with 'ubi_thread()' which diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c0ed60e8ade97..54b0186915fbf 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) be32_to_cpu(ec_hdr->vid_hdr_offset)); printk(KERN_DEBUG "\tdata_offset %d\n", be32_to_cpu(ec_hdr->data_offset)); + printk(KERN_DEBUG "\timage_seq %d\n", + be32_to_cpu(ec_hdr->image_seq)); printk(KERN_DEBUG "\thdr_crc %#08x\n", be32_to_cpu(ec_hdr->hdr_crc)); printk(KERN_DEBUG "erase counter header hexdump:\n"); diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index c8edbfd09b64b..b587140110916 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -563,15 +563,16 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum) * This function returns zero if the erase counter header is OK, and %1 if * not. */ -static int validate_ec_hdr(const struct ubi_device *ubi, +static int validate_ec_hdr(struct ubi_device *ubi, const struct ubi_ec_hdr *ec_hdr) { long long ec; - int vid_hdr_offset, leb_start; + int vid_hdr_offset, leb_start, image_seq; ec = be64_to_cpu(ec_hdr->ec); vid_hdr_offset = be32_to_cpu(ec_hdr->vid_hdr_offset); leb_start = be32_to_cpu(ec_hdr->data_offset); + image_seq = be32_to_cpu(ec_hdr->image_seq); if (ec_hdr->version != UBI_VERSION) { ubi_err("node with incompatible UBI version found: " @@ -597,6 +598,15 @@ static int validate_ec_hdr(const struct ubi_device *ubi, goto bad; } + if (!ubi->image_seq_set) { + ubi->image_seq = image_seq; + ubi->image_seq_set = 1; + } else if (ubi->image_seq != image_seq) { + ubi_err("bad image sequence number %d, expected %d", + image_seq, ubi->image_seq); + goto bad; + } + return 0; bad: @@ -742,6 +752,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, ec_hdr->version = UBI_VERSION; ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset); ec_hdr->data_offset = cpu_to_be32(ubi->leb_start); + ec_hdr->image_seq = cpu_to_be32(ubi->image_seq); crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); ec_hdr->hdr_crc = cpu_to_be32(crc); diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c3d653ba5ca01..72570ed7d33fb 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -910,6 +910,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) if (si->is_empty) ubi_msg("empty MTD device detected"); + ubi->image_seq_set = 1; + /* * In case of unknown erase counter we use the mean erase counter * value. diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 8419fdccc79cb..503ea9b273094 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -129,6 +129,7 @@ enum { * @ec: the erase counter * @vid_hdr_offset: where the VID header starts * @data_offset: where the user data start + * @image_seq: image sequence number * @padding2: reserved for future, zeroes * @hdr_crc: erase counter header CRC checksum * @@ -144,6 +145,14 @@ enum { * volume identifier header and user data, relative to the beginning of the * physical eraseblock. These values have to be the same for all physical * eraseblocks. + * + * The @image_seq field is used to validate a UBI image that has been prepared + * for a UBI device. The @image_seq value can be any value, but it must be the + * same on all eraseblocks. UBI will ensure that all new erase counter headers + * also contain this value, and will check the value when scanning at start-up. + * One way to make use of @image_seq is to increase its value by one every time + * an image is flashed over an existing image, then, if the flashing does not + * complete, UBI will detect the error when scanning. */ struct ubi_ec_hdr { __be32 magic; @@ -152,7 +161,8 @@ struct ubi_ec_hdr { __be64 ec; /* Warning: the current limit is 31-bit anyway! */ __be32 vid_hdr_offset; __be32 data_offset; - __u8 padding2[36]; + __be32 image_seq; + __u8 padding2[32]; __be32 hdr_crc; } __attribute__ ((packed)); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 28acd133c9979..bb372c4222b7d 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -301,6 +301,8 @@ struct ubi_wl_entry; * @vol->readers, @vol->writers, @vol->exclusive, * @vol->ref_count, @vol->mapping and @vol->eba_tbl. * @ref_count: count of references on the UBI device + * @image_seq: image sequence number recorded on EC headers + * @image_seq_set: indicates @image_seq is known * * @rsvd_pebs: count of reserved physical eraseblocks * @avail_pebs: count of available physical eraseblocks @@ -390,6 +392,8 @@ struct ubi_device { struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; spinlock_t volumes_lock; int ref_count; + int image_seq; + int image_seq_set; int rsvd_pebs; int avail_pebs; -- GitLab From fe96efc1a3c049f0a1bcd9b65e0faeb751ce5ec6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Tue, 30 Jun 2009 16:11:59 +0300 Subject: [PATCH 0727/1002] UBI: nicify image sequence number handling Move the image seq. number handling from I/O level to the scanning lever, where it really belongs to. Move the @image_seq_set variable to the @struct ubi_scan_info structure, which exists only during scanning. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/io.c | 14 ++------------ drivers/mtd/ubi/scan.c | 16 ++++++++++++++-- drivers/mtd/ubi/scan.h | 2 ++ drivers/mtd/ubi/ubi.h | 2 -- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index b587140110916..1ea14218de021 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -563,16 +563,15 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum) * This function returns zero if the erase counter header is OK, and %1 if * not. */ -static int validate_ec_hdr(struct ubi_device *ubi, +static int validate_ec_hdr(const struct ubi_device *ubi, const struct ubi_ec_hdr *ec_hdr) { long long ec; - int vid_hdr_offset, leb_start, image_seq; + int vid_hdr_offset, leb_start; ec = be64_to_cpu(ec_hdr->ec); vid_hdr_offset = be32_to_cpu(ec_hdr->vid_hdr_offset); leb_start = be32_to_cpu(ec_hdr->data_offset); - image_seq = be32_to_cpu(ec_hdr->image_seq); if (ec_hdr->version != UBI_VERSION) { ubi_err("node with incompatible UBI version found: " @@ -598,15 +597,6 @@ static int validate_ec_hdr(struct ubi_device *ubi, goto bad; } - if (!ubi->image_seq_set) { - ubi->image_seq = image_seq; - ubi->image_seq_set = 1; - } else if (ubi->image_seq != image_seq) { - ubi_err("bad image sequence number %d, expected %d", - image_seq, ubi->image_seq); - goto bad; - } - return 0; bad: diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 72570ed7d33fb..f60895ee0aebd 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, si->is_empty = 0; if (!ec_corr) { + int image_seq; + /* Make sure UBI version is OK */ if (ech->version != UBI_VERSION) { ubi_err("this UBI version is %d, image version is %d", @@ -778,6 +780,18 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ubi_dbg_dump_ec_hdr(ech); return -EINVAL; } + + image_seq = be32_to_cpu(ech->ec); + if (!si->image_seq_set) { + ubi->image_seq = image_seq; + si->image_seq_set = 1; + } else if (ubi->image_seq != image_seq) { + ubi_err("bad image sequence number %d in PEB %d, " + "expected %d", image_seq, pnum, ubi->image_seq); + ubi_dbg_dump_ec_hdr(ech); + return -EINVAL; + } + } /* OK, we've done with the EC header, let's look at the VID header */ @@ -910,8 +924,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) if (si->is_empty) ubi_msg("empty MTD device detected"); - ubi->image_seq_set = 1; - /* * In case of unknown erase counter we use the mean erase counter * value. diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 61df208e2f207..1017cf12def56 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -102,6 +102,7 @@ struct ubi_scan_volume { * @mean_ec: mean erase counter value * @ec_sum: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec + * @image_seq_set: indicates @ubi->image_seq is known * * This data structure contains the result of scanning and may be used by other * UBI sub-systems to build final UBI data structures, further error-recovery @@ -124,6 +125,7 @@ struct ubi_scan_info { int mean_ec; uint64_t ec_sum; int ec_count; + int image_seq_set; }; struct ubi_device; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index bb372c4222b7d..64604e8809eca 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -302,7 +302,6 @@ struct ubi_wl_entry; * @vol->ref_count, @vol->mapping and @vol->eba_tbl. * @ref_count: count of references on the UBI device * @image_seq: image sequence number recorded on EC headers - * @image_seq_set: indicates @image_seq is known * * @rsvd_pebs: count of reserved physical eraseblocks * @avail_pebs: count of available physical eraseblocks @@ -393,7 +392,6 @@ struct ubi_device { spinlock_t volumes_lock; int ref_count; int image_seq; - int image_seq_set; int rsvd_pebs; int avail_pebs; -- GitLab From 3175da83a0a85fa03c9c34061906a9ca0725af0d Mon Sep 17 00:00:00 2001 From: Hans Verkuil <hverkuil@xs4all.nl> Date: Fri, 26 Jun 2009 15:35:04 -0300 Subject: [PATCH 0728/1002] V4L/DVB (12153): ttpci: config TTPCI_EEPROM depends on I2C If I2C is not enabled, then we shouldn't build ttpci_eeprom.c. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/dvb/ttpci/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 68eb4493f991f..d8d4214fd65f2 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,5 +1,6 @@ config TTPCI_EEPROM tristate + depends on I2C default n config DVB_AV7110 -- GitLab From 14df2ccead8f6da5a9c8f904fc629aaf849b7e55 Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier <hbmeier@hni.uni-paderborn.de> Date: Wed, 24 Jun 2009 10:31:25 -0300 Subject: [PATCH 0729/1002] V4L/DVB (12159): soc_camera: Fix debug output of supported formats count The supported formats count must be set to 0 after debug output right before the second pass. Signed-off-by: Stefan Herbrechtsmeier <hbmeier@hni.uni-paderborn.de> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 16f595d4337ab..78010abfe8be0 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -237,11 +237,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return -ENOMEM; icd->num_user_formats = fmts; - fmts = 0; dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); /* Second pass - actually fill data formats */ + fmts = 0; for (i = 0; i < icd->num_formats; i++) if (!ici->ops->get_formats) { icd->user_formats[i].host_fmt = icd->formats + i; -- GitLab From c06950ae4dccf59566fec7ae269aaeb24685c16c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Wed, 24 Jun 2009 10:31:25 -0300 Subject: [PATCH 0730/1002] V4L/DVB (12160): soc-camera: fix missing clean up on error path If soc_camera_init_user_formats() fails in soc_camera_probe(), we have to call client's .remove() method to unregister the video device. Reported-by: Kuninori Morimoto <morimoto.kuninori@renesas.com> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/soc_camera.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 78010abfe8be0..9f5ae81678553 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -877,8 +877,11 @@ static int soc_camera_probe(struct device *dev) (unsigned short)~0; ret = soc_camera_init_user_formats(icd); - if (ret < 0) + if (ret < 0) { + if (icd->ops->remove) + icd->ops->remove(icd); goto eiufmt; + } icd->height = DEFAULT_HEIGHT; icd->width = DEFAULT_WIDTH; @@ -902,8 +905,10 @@ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + mutex_lock(&icd->video_lock); if (icd->ops->remove) icd->ops->remove(icd); + mutex_unlock(&icd->video_lock); soc_camera_free_user_formats(icd); @@ -1145,6 +1150,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) } EXPORT_SYMBOL(soc_camera_video_start); +/* Called from client .remove() methods with .video_lock held */ void soc_camera_video_stop(struct soc_camera_device *icd) { struct video_device *vdev = icd->vdev; @@ -1154,10 +1160,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd) if (!icd->dev.parent || !vdev) return; - mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&icd->video_lock); } EXPORT_SYMBOL(soc_camera_video_stop); -- GitLab From 6e707b4c6d1fcf0fca6a4525e0ff66d35e21a517 Mon Sep 17 00:00:00 2001 From: Andy Walls <awalls@radix.net> Date: Thu, 11 Jun 2009 07:57:50 -0300 Subject: [PATCH 0731/1002] V4L/DVB (12167): tuner-xc2028: Fix 7 MHz DVB-T The following patch should fix 7 MHz DVB-T with the XC3028 using the DTV7 firmware from the xc3028-v27.fw firmware image. Tested-by: Terry Wu <terrywu2009@gmail.com> [mchehab@redhat.com: thanks to John Ferlito, we have a real test in Australia] Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/common/tuners/tuner-xc2028.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index b6da9c3873fef..aa20ce8cc668b 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -1096,8 +1096,19 @@ static int xc2028_set_params(struct dvb_frontend *fe, } /* All S-code tables need a 200kHz shift */ - if (priv->ctrl.demod) + if (priv->ctrl.demod) { demod = priv->ctrl.demod + 200; + /* + * The DTV7 S-code table needs a 700 kHz shift. + * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this + * + * DTV7 is only used in Australia. Germany or Italy may also + * use this firmware after initialization, but a tune to a UHF + * channel should then cause DTV78 to be used. + */ + if (type & DTV7) + demod += 500; + } return generic_set_freq(fe, p->frequency, T_DIGITAL_TV, type, 0, demod); -- GitLab From 637fb3d70b1e53a127cba5ffae5aa3b2b9f57df6 Mon Sep 17 00:00:00 2001 From: Andy Walls <awalls@radix.net> Date: Fri, 3 Jul 2009 11:30:27 -0300 Subject: [PATCH 0732/1002] V4L/DVB (12180): cx18: Update Yuan MPC-718 card entry with better information and guesses Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/cx18/cx18-cards.c | 34 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index c92a25036f0e2..80ee7bd64e243 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { static const struct cx18_card cx18_card_mpc718 = { .type = CX18_CARD_YUAN_MPC718, - .name = "Yuan MPC718", - .comment = "Analog video capture works; some audio line in may not.\n", + .name = "Yuan MPC718 MiniPCI DVB-T/Analog", + .comment = "Experimenters needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | + CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = { { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, - { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, - { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, - { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, }, - .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 }, .tuners = { /* XC3028 tuner */ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, + /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, .ddr = { - /* Probably Samsung K4D263238G-VC33 memory */ - .chip_config = 0x003, - .refresh = 0x30c, - .timing1 = 0x23230b73, - .timing2 = 0x08, + /* Hynix HY5DU283222B DDR RAM */ + .chip_config = 0x303, + .refresh = 0x3bd, + .timing1 = 0x36320966, + .timing2 = 0x1f, .tune_lane = 0, .initial_emrs = 2, }, + .gpio_init.initial_value = 0x1, + .gpio_init.direction = 0x3, + /* FIXME - these GPIO's are just guesses */ + .gpio_audio_input = { .mask = 0x3, + .tuner = 0x1, + .linein = 0x3, + .radio = 0x1 }, .xceive_pin = 0, .pci_list = cx18_pci_mpc718, .i2c = &cx18_i2c_std, -- GitLab From 9f38a920b232800fd4000ba3d4617b41198e017e Mon Sep 17 00:00:00 2001 From: Andy Walls <awalls@radix.net> Date: Fri, 3 Jul 2009 11:33:17 -0300 Subject: [PATCH 0733/1002] V4L/DVB (12181): get_dvb_firmware: Add Yuan MPC718 MT352 DVB-T "firmware" extraction Add routine to support extracting the MT352 DVB-T demodulator initialization sequence for Yuan MPC718 cards for use by the cx18 driver. This routine uses a hueristic for extracting a good sequence. It should work on all different versions of the "yuanrap.sys" file, given the way the MT352 tuning sequences are stored in all versions of that file I have seen so far. However, the current patch simply looks for one specific archive URL. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/dvb/get_dvb_firmware | 52 +++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index a52adfc9a57fe..64174d6258f01 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -25,7 +25,7 @@ use IO::Handle; "tda10046lifeview", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "or51211", "or51132_qam", "or51132_vsb", "bluebird", - "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" ); + "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718" ); # Check args syntax() if (scalar(@ARGV) != 1); @@ -381,6 +381,56 @@ sub cx18 { $allfiles; } +sub mpc718 { + my $archive = 'Yuan MPC718 TV Tuner Card 2.13.10.1016.zip'; + my $url = "ftp://ftp.work.acer-euro.com/desktop/aspire_idea510/vista/Drivers/$archive"; + my $fwfile = "dvb-cx18-mpc718-mt352.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + + checkstandard(); + wgetfile($archive, $url); + unzip($archive, $tmpdir); + + my $sourcefile = "$tmpdir/Yuan MPC718 TV Tuner Card 2.13.10.1016/mpc718_32bit/yuanrap.sys"; + my $found = 0; + + open IN, '<', $sourcefile or die "Couldn't open $sourcefile to extract $fwfile data\n"; + binmode IN; + open OUT, '>', $fwfile; + binmode OUT; + { + # Block scope because we change the line terminator variable $/ + my $prevlen = 0; + my $currlen; + + # Buried in the data segment are 3 runs of almost identical + # register-value pairs that end in 0x5d 0x01 which is a "TUNER GO" + # command for the MT352. + # Pull out the middle run (because it's easy) of register-value + # pairs to make the "firmware" file. + + local $/ = "\x5d\x01"; # MT352 "TUNER GO" + + while (<IN>) { + $currlen = length($_); + if ($prevlen == $currlen || $currlen <= 64) { + chop; chop; # Get rid of "TUNER GO" + s/^\0\0//; # get rid of leading 00 00 if it's there + printf OUT "$_"; + $found = 1; + last; + } + } + } + close OUT; + close IN; + if (!$found) { + unlink $fwfile; + die "Couldn't find valid register-value sequence in $sourcefile for $fwfile\n"; + } + $fwfile; +} + sub cx23885 { my $url = "http://linuxtv.org/downloads/firmware/"; -- GitLab From ff861fb21e44ab178eddc6a1dd7c5478e3eb2ec5 Mon Sep 17 00:00:00 2001 From: Andy Walls <awalls@radix.net> Date: Fri, 3 Jul 2009 11:54:40 -0300 Subject: [PATCH 0734/1002] V4L/DVB (12182): cx18: Add DVB-T support for Yuan MPC-718 cards with an MT352 or ZL10353 Add DVB-T support for Yuan MPC-718 cards with an MT352 or ZL10353 demodulator. There are apparently some units with a DiBcom demodulator which could be supported by one of the dib7000 modules - but this is not implemented in the cx18 driver (yet). Due to lack of porgramming details for the MT352 and the mt352 module requiring a "demod_init" function, a "firmware" must be obtained and loaded to get DVB-T working for Yuan MPC-718 cards with an MT352. Tested-by: Steve Firth <firth650@btinternet.com> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/cx18/cx18-cards.c | 4 +- drivers/media/video/cx18/cx18-dvb.c | 160 ++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 80ee7bd64e243..36f2d76006fd4 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -204,8 +204,8 @@ static const struct cx18_card cx18_card_mpc718 = { .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | - CX18_HW_GPIO_RESET_CTRL, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623ef49..51a0c33b25b7f 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -30,6 +30,10 @@ #include "s5h1409.h" #include "mxl5005s.h" #include "zl10353.h" + +#include <linux/firmware.h> +#include "mt352.h" +#include "mt352_priv.h" #include "tuner-xc2028.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define CX18_CLOCK_ENABLE2 0xc71024 #define CX18_DMUX_CLK_MASK 0x0080 +/* + * CX18_CARD_HVR_1600_ESMT + * CX18_CARD_HVR_1600_SAMSUNG + */ + static struct mxl5005s_config hauppauge_hvr1600_tuner = { .i2c_address = 0xC6 >> 1, .if_freq = IF_FREQ_5380000HZ, @@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +/* + * CX18_CARD_LEADTEK_DVR3100H + */ /* Information/confirmation of proper config values provided by Terry Wu */ static struct zl10353_config leadtek_dvr3100h_demod = { .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ @@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; +/* + * CX18_CARD_YUAN_MPC718 + */ +/* + * Due to + * + * 1. an absence of information on how to prgram the MT352 + * 2. the Linux mt352 module pushing MT352 initialzation off onto us here + * + * We have to use an init sequence that *you* must extract from the Windows + * driver (yuanrap.sys) and which we load as a firmware. + * + * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual + * with chip programming details, then I can remove this annoyance. + */ +static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, + const struct firmware **fw) +{ + struct cx18 *cx = stream->cx; + const char *fn = "dvb-cx18-mpc718-mt352.fw"; + int ret; + + ret = request_firmware(fw, fn, &cx->pci_dev->dev); + if (ret) + CX18_ERR("Unable to open firmware file %s\n", fn); + else { + size_t sz = (*fw)->size; + if (sz < 2 || sz > 64 || (sz % 2) != 0) { + CX18_ERR("Firmware %s has a bad size: %lu bytes\n", + fn, (unsigned long) sz); + ret = -EILSEQ; + release_firmware(*fw); + *fw = NULL; + } + } + + if (ret) { + CX18_ERR("The MPC718 board variant with the MT352 DVB-T" + "demodualtor will not work without it\n"); + CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " + "mpc718' if you need the firmware\n"); + } + return ret; +} + +static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) +{ + struct cx18_dvb *dvb = container_of(fe->dvb, + struct cx18_dvb, dvb_adapter); + struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); + const struct firmware *fw = NULL; + int ret; + int i; + u8 buf[3]; + + ret = yuan_mpc718_mt352_reqfw(stream, &fw); + if (ret) + return ret; + + /* Loop through all the register-value pairs in the firmware file */ + for (i = 0; i < fw->size; i += 2) { + buf[0] = fw->data[i]; + /* Intercept a few registers we want to set ourselves */ + switch (buf[0]) { + case TRL_NOMINAL_RATE_0: + /* Set our custom OFDM bandwidth in the case below */ + break; + case TRL_NOMINAL_RATE_1: + /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ + /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ + /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ + buf[1] = 0x72; + buf[2] = 0x49; + mt352_write(fe, buf, 3); + break; + case INPUT_FREQ_0: + /* Set our custom IF in the case below */ + break; + case INPUT_FREQ_1: + /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ + buf[1] = 0x31; + buf[2] = 0xc0; + mt352_write(fe, buf, 3); + break; + default: + /* Pass through the register-value pair from the fw */ + buf[1] = fw->data[i+1]; + mt352_write(fe, buf, 2); + break; + } + } + + buf[0] = (u8) TUNER_GO; + buf[1] = 0x01; /* Go */ + mt352_write(fe, buf, 2); + release_firmware(fw); + return 0; +} + +static struct mt352_config yuan_mpc718_mt352_demod = { + .demod_address = 0x1e >> 1, + .adc_clock = 20480, /* 20.480 MHz */ + .if2 = 4560, /* 4.560 MHz */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .demod_init = yuan_mpc718_mt352_init, +}; + +static struct zl10353_config yuan_mpc718_zl10353_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ +}; + static int dvb_register(struct cx18_stream *stream); /* Kernel DVB framework calls this when the feed needs to start. @@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) break; case CX18_CARD_LEADTEK_DVR3100H: + case CX18_CARD_YUAN_MPC718: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; + case CX18_CARD_YUAN_MPC718: + /* + * TODO + * Apparently, these cards also could instead have a + * DiBcom demod supported by one of the db7000 drivers + */ + dvb->fe = dvb_attach(mt352_attach, + &yuan_mpc718_mt352_demod, + &cx->i2c_adap[1]); + if (dvb->fe == NULL) + dvb->fe = dvb_attach(zl10353_attach, + &yuan_mpc718_zl10353_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; -- GitLab From 509dd025a4ac6f32921211557cfd434b81d8d7a7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Tue, 30 Jun 2009 16:07:26 -0300 Subject: [PATCH 0735/1002] V4L/DVB (12148): move V4L2_PIX_FMT_SGRBG8 to the proper place Instead of defining a new pif format on an internal header, move it to the V4L2 API header. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/gspca/stv06xx/stv06xx.h | 4 ---- include/linux/videodev2.h | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 9df7137fe67ec..992ce530f138d 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -36,10 +36,6 @@ #define STV_ISOC_ENDPOINT_ADDR 0x81 -#ifndef V4L2_PIX_FMT_SGRBG8 -#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') -#endif - #define STV_REG23 0x0423 /* Control registers of the STV0600 ASIC */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 8a025d5109046..95846d9880114 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -318,6 +318,8 @@ struct v4l2_pix_format { /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ + /* * 10bit raw bayer, expanded to 16 bits * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb... -- GitLab From f35b9e8039c04f0cb9fe3a051ce941b1524a8798 Mon Sep 17 00:00:00 2001 From: Michael Krufky <mkrufky@kernellabs.com> Date: Fri, 8 May 2009 22:39:24 -0300 Subject: [PATCH 0736/1002] V4L/DVB (12165): cx23885: override set_frontend to allow rf input path switching on the HVR1275 Use separate RF input spigots for Antennae and Cable. Reviewed-by: Steven Toth <stoth@kernellabs.com> Signed-off-by: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/cx23885/cx23885-dvb.c | 29 +++++++++++++++++++++++ drivers/media/video/cx23885/cx23885.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 48a975134ac5f..a851a81e257e2 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -463,6 +463,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = { .if_khz = 5380, }; +static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1275: + switch (param->u.vsb.modulation) { + case VSB_8: + cx23885_gpio_clear(dev, GPIO_5); + break; + case QAM_64: + case QAM_256: + default: + cx23885_gpio_set(dev, GPIO_5); + break; + } + break; + } + return (port->set_frontend_save) ? + port->set_frontend_save(fe, param) : -ENODEV; +} + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -502,6 +526,11 @@ static int dvb_register(struct cx23885_tsport *port) 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } + + /* define bridge override to set_frontend */ + port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; + fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; + break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 1a2ac518a3f1a..f4e22b0af7d2b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -288,6 +288,8 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; + int (*set_frontend_save) (struct dvb_frontend *, + struct dvb_frontend_parameters *); }; struct cx23885_dev { -- GitLab From b179bc4579f67c6f1df524c48b28cacf0c7a1b91 Mon Sep 17 00:00:00 2001 From: Michael Krufky <mkrufky@kernellabs.com> Date: Tue, 16 Jun 2009 17:08:17 -0300 Subject: [PATCH 0737/1002] V4L/DVB (12166): cx23885: add FIXME comment above set_frontend override add FIXME comment to indicate that the set_frontend override is a temporary hack. This will be done a better way in the next kernel. Signed-off-by: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/cx23885/cx23885-dvb.c | 1 + drivers/media/video/cx23885/cx23885.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index a851a81e257e2..86ac529e62be0 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -527,6 +527,7 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr127x_config); } + /* FIXME: temporary hack */ /* define bridge override to set_frontend */ port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index f4e22b0af7d2b..214a55e943b78 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -288,6 +288,8 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; + + /* FIXME: temporary hack */ int (*set_frontend_save) (struct dvb_frontend *, struct dvb_frontend_parameters *); }; -- GitLab From 7dfba00d05f3c7db9510f3b54a472981cf1521af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Mon, 29 Jun 2009 05:41:26 -0300 Subject: [PATCH 0738/1002] V4L/DVB (12135): Add a driver for mt9v011 sensor Adds driver for mt9v011 based on its datasheet, available at: http://download.micron.com/pdf/datasheets/imaging/MT9V011.pdf The driver was tested with a webcam that will be added on a next patch. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/Kconfig | 8 + drivers/media/video/Makefile | 1 + drivers/media/video/mt9v011.c | 355 ++++++++++++++++++++++++++++++++ drivers/media/video/mt9v011.h | 35 ++++ include/media/v4l2-chip-ident.h | 3 + 5 files changed, 402 insertions(+) create mode 100644 drivers/media/video/mt9v011.c create mode 100644 drivers/media/video/mt9v011.h diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 061e147f6f263..84b6fc15519d1 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -312,6 +312,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_MT9V011 + tristate "Micron mt9v011 sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This is a Video4Linux2 sensor-level driver for the Micron + mt0v011 1.3 Mpixel camera. It currently only works with the + em28xx driver. + config VIDEO_TCM825X tristate "TCM825x camera sensor support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7fb3add1b3879..9f2e3214a4820 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c new file mode 100644 index 0000000000000..4389197cedd70 --- /dev/null +++ b/drivers/media/video/mt9v011.c @@ -0,0 +1,355 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#include <linux/i2c.h> +#include <linux/videodev2.h> +#include <linux/delay.h> +#include <media/v4l2-device.h> +#include "mt9v011.h" +#include <media/v4l2-i2c-drv.h> +#include <media/v4l2-chip-ident.h> + +MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_LICENSE("GPL"); + + +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-2)"); + +/* supported controls */ +static struct v4l2_queryctrl mt9v011_qctrl[] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = (1 << 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, +}; + +struct mt9v011 { + struct v4l2_subdev sd; + + u16 global_gain, red_bal, blue_bal; +}; + +static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mt9v011, sd); +} + +static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + __be16 buffer; + int rc, val; + + if (1 != (rc = i2c_master_send(c, &addr, 1))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 1)\n", rc); + + msleep(10); + + if (2 != (rc = i2c_master_recv(c, (char *)&buffer, 2))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 1)\n", rc); + + val = be16_to_cpu(buffer); + + v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); + + return val; +} + +static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, + u16 value) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned char buffer[3]; + int rc; + + buffer[0] = addr; + buffer[1] = value >> 8; + buffer[2] = value & 0xff; + + v4l2_dbg(2, debug, sd, + "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); + if (3 != (rc = i2c_master_send(c, buffer, 3))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 3)\n", rc); +} + + +struct i2c_reg_value { + unsigned char reg; + u16 value; +}; + +/* + * Values used at the original driver + * Some values are marked as Reserved at the datasheet + */ +static const struct i2c_reg_value mt9v011_init_default[] = { + /* guessed meaning - as mt9m111 */ + { R0D_MT9V011_RESET, 0x0001 }, + { R0D_MT9V011_RESET, 0x0000 }, + { R01_MT9V011_ROWSTART, 0x0008 }, + { R02_MT9V011_COLSTART, 0x0014 }, + { R03_MT9V011_HEIGHT, 0x01e0 }, + { R04_MT9V011_WIDTH, 0x0280 }, + { R05_MT9V011_HBLANK, 0x0001 }, + { R05_MT9V011_HBLANK, 0x0001 }, + { R0A_MT9V011_CLK_SPEED, 0x0000 }, + { R05_MT9V011_HBLANK, 0x000a }, + { 0x30, 0x0005 }, + { 0x34, 0x0100 }, + { 0x3d, 0x068f }, + { 0x40, 0x01e0 }, + { 0x52, 0x0100 }, + { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ + { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ + { 0x62, 0x041a }, /* Datasheet default 0x0418 */ + { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, + { R20_MT9V011_READ_MODE, 0x1100 }, +}; + +static void set_balance(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + u16 green1_gain, green2_gain, blue_gain, red_gain; + + green1_gain = core->global_gain; + green2_gain = core->global_gain; + + blue_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + red_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain); + mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green1_gain); + mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); + mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); +} + +static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) +{ + u16 version; + int i; + + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + + if (version != MT9V011_VERSION) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + version); + return -EINVAL; + + } + + for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) + mt9v011_write(sd, mt9v011_init_default[i].reg, + mt9v011_init_default[i].value); + + set_balance(sd); + + return 0; +}; + +static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + + v4l2_dbg(1, debug, sd, "g_ctrl called\n"); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + ctrl->value = core->global_gain; + return 0; + case V4L2_CID_RED_BALANCE: + ctrl->value = core->red_bal; + return 0; + case V4L2_CID_BLUE_BALANCE: + ctrl->value = core->blue_bal; + return 0; + } + return -EINVAL; +} + +static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + u8 i, n; + n = ARRAY_SIZE(mt9v011_qctrl); + + for (i = 0; i < n; i++) { + if (ctrl->id != mt9v011_qctrl[i].id) + continue; + if (ctrl->value < mt9v011_qctrl[i].minimum || + ctrl->value > mt9v011_qctrl[i].maximum) + return -ERANGE; + v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", + ctrl->id, ctrl->value); + break; + } + + switch (ctrl->id) { + case V4L2_CID_GAIN: + core->global_gain = ctrl->value; + break; + case V4L2_CID_RED_BALANCE: + core->red_bal = ctrl->value; + break; + case V4L2_CID_BLUE_BALANCE: + core->blue_bal = ctrl->value; + break; + default: + return -EINVAL; + } + + set_balance(sd); + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v011_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + reg->val = mt9v011_read(sd, reg->reg & 0xff); + reg->size = 2; + + return 0; +} + +static int mt9v011_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); + + return 0; +} +#endif + +static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, + MT9V011_VERSION); +} + +static const struct v4l2_subdev_core_ops mt9v011_core_ops = { + .g_ctrl = mt9v011_g_ctrl, + .s_ctrl = mt9v011_s_ctrl, + .reset = mt9v011_reset, + .g_chip_ident = mt9v011_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v011_g_register, + .s_register = mt9v011_s_register, +#endif +}; + +static const struct v4l2_subdev_ops mt9v011_ops = { + .core = &mt9v011_core_ops, +}; + + +/**************************************************************************** + I2C Client & Driver + ****************************************************************************/ + +static int mt9v011_probe(struct i2c_client *c, + const struct i2c_device_id *id) +{ + struct mt9v011 *core; + struct v4l2_subdev *sd; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(c->adapter, + I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -EIO; + + core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); + if (!core) + return -ENOMEM; + + core->global_gain = 0x0024; + + sd = &core->sd; + v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); + v4l_info(c, "chip found @ 0x%02x (%s)\n", + c->addr << 1, c->adapter->name); + + return 0; +} + +static int mt9v011_remove(struct i2c_client *c) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(c); + + v4l2_dbg(1, debug, sd, + "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", + c->addr << 1); + + v4l2_device_unregister_subdev(sd); + kfree(to_mt9v011(sd)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static const struct i2c_device_id mt9v011_id[] = { + { "mt9v011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9v011_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "mt9v011", + .probe = mt9v011_probe, + .remove = mt9v011_remove, + .id_table = mt9v011_id, +}; diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h new file mode 100644 index 0000000000000..9e443ee305585 --- /dev/null +++ b/drivers/media/video/mt9v011.h @@ -0,0 +1,35 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#ifndef MT9V011_H_ +#define MT9V011_H_ + +#define R00_MT9V011_CHIP_VERSION 0x00 +#define R01_MT9V011_ROWSTART 0x01 +#define R02_MT9V011_COLSTART 0x02 +#define R03_MT9V011_HEIGHT 0x03 +#define R04_MT9V011_WIDTH 0x04 +#define R05_MT9V011_HBLANK 0x05 +#define R06_MT9V011_VBLANK 0x06 +#define R07_MT9V011_OUT_CTRL 0x07 +#define R09_MT9V011_SHUTTER_WIDTH 0x09 +#define R0A_MT9V011_CLK_SPEED 0x0a +#define R0B_MT9V011_RESTART 0x0b +#define R0C_MT9V011_SHUTTER_DELAY 0x0c +#define R0D_MT9V011_RESET 0x0d +#define R1E_MT9V011_DIGITAL_ZOOM 0x1e +#define R20_MT9V011_READ_MODE 0x20 +#define R2B_MT9V011_GREEN_1_GAIN 0x2b +#define R2C_MT9V011_BLUE_GAIN 0x2c +#define R2D_MT9V011_RED_GAIN 0x2d +#define R2E_MT9V011_GREEN_2_GAIN 0x2e +#define R35_MT9V011_GLOBAL_GAIN 0x35 +#define RF1_MT9V011_CHIP_ENABLE 0xf1 + +#define MT9V011_VERSION 0x8243 + +#endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 4d7e2272c42f0..11a4a2d3e364f 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -155,6 +155,9 @@ enum { /* module cafe_ccic, just ident 8801 */ V4L2_IDENT_CAFE = 8801, + /* module mt9v011, just ident 8243 */ + V4L2_IDENT_MT9V011 = 8243, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, -- GitLab From afe09f821ffa733d1cbfbf4e7cc41bd1cb8dcffb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Mon, 29 Jun 2009 11:03:22 -0300 Subject: [PATCH 0739/1002] V4L/DVB (12136): mt9v011: Some fixes at the register initialization table Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/mt9v011.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index 4389197cedd70..cd5e119f40a5b 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -117,17 +117,25 @@ struct i2c_reg_value { * Some values are marked as Reserved at the datasheet */ static const struct i2c_reg_value mt9v011_init_default[] = { - /* guessed meaning - as mt9m111 */ { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, + { R01_MT9V011_ROWSTART, 0x0008 }, { R02_MT9V011_COLSTART, 0x0014 }, { R03_MT9V011_HEIGHT, 0x01e0 }, { R04_MT9V011_WIDTH, 0x0280 }, - { R05_MT9V011_HBLANK, 0x0001 }, - { R05_MT9V011_HBLANK, 0x0001 }, + { R05_MT9V011_HBLANK, 0x007b }, + { R06_MT9V011_VBLANK, 0x001c }, + { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, { R0A_MT9V011_CLK_SPEED, 0x0000 }, - { R05_MT9V011_HBLANK, 0x000a }, + { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, + { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, + { R20_MT9V011_READ_MODE, 0x1100 }, + + /* + * Those registers are not docummented at the datasheet. + * However, the original driver initializes them + */ { 0x30, 0x0005 }, { 0x34, 0x0100 }, { 0x3d, 0x068f }, @@ -136,8 +144,8 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ { 0x62, 0x041a }, /* Datasheet default 0x0418 */ - { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, - { R20_MT9V011_READ_MODE, 0x1100 }, + + { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ }; static void set_balance(struct v4l2_subdev *sd) -- GitLab From fbe2800c932573e90e38a9c703165839e0c00515 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Mon, 29 Jun 2009 11:12:05 -0300 Subject: [PATCH 0740/1002] V4L/DVB (12137): mt9v011: CodingStyle fixes Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/mt9v011.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index cd5e119f40a5b..58a6194367830 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -71,15 +71,17 @@ static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) __be16 buffer; int rc, val; - if (1 != (rc = i2c_master_send(c, &addr, 1))) + rc = i2c_master_send(c, &addr, 1); + if (rc != 1) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc); msleep(10); - if (2 != (rc = i2c_master_recv(c, (char *)&buffer, 2))) + rc = i2c_master_recv(c, (char *)&buffer, 2); + if (rc != 2) v4l2_dbg(0, debug, sd, - "i2c i/o error: rc == %d (should be 1)\n", rc); + "i2c i/o error: rc == %d (should be 2)\n", rc); val = be16_to_cpu(buffer); @@ -101,7 +103,8 @@ static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, v4l2_dbg(2, debug, sd, "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); - if (3 != (rc = i2c_master_send(c, buffer, 3))) + rc = i2c_master_send(c, &buffer, 3); + if (rc != 3) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 3)\n", rc); } -- GitLab From 27fe4a30a211a0561c72b0e519997e91fa91c452 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Sat, 4 Jul 2009 08:03:48 -0300 Subject: [PATCH 0741/1002] V4L/DVB (12173): mt9v011: properly calculate image resolution registers Instead of working with a table of precalculated values, fill them with the proper values. Also, adds format functions that allow changing the resolution, by cropping the image to the center of the sensor. While here, move the sensor version check to the probe routine, to indicate to the caller if the sensor is not supported by this driver. Also, fixes a stupid bug where we're using &buffer[] instead of buffer[]. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/mt9v011.c | 114 ++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 20 deletions(-) diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index 58a6194367830..3ed9511da8edc 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -56,6 +56,7 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = { struct mt9v011 { struct v4l2_subdev sd; + unsigned width, height; u16 global_gain, red_bal, blue_bal; }; @@ -103,7 +104,7 @@ static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, v4l2_dbg(2, debug, sd, "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); - rc = i2c_master_send(c, &buffer, 3); + rc = i2c_master_send(c, buffer, 3); if (rc != 3) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 3)\n", rc); @@ -123,12 +124,6 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, - { R01_MT9V011_ROWSTART, 0x0008 }, - { R02_MT9V011_COLSTART, 0x0014 }, - { R03_MT9V011_HEIGHT, 0x01e0 }, - { R04_MT9V011_WIDTH, 0x0280 }, - { R05_MT9V011_HBLANK, 0x007b }, - { R06_MT9V011_VBLANK, 0x001c }, { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, @@ -171,25 +166,40 @@ static void set_balance(struct v4l2_subdev *sd) mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); } +static void set_res(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned vstart, hstart; + + /* + * The mt9v011 doesn't have scaling. So, in order to select the desired + * resolution, we're cropping at the middle of the sensor. + * hblank and vblank should be adjusted, in order to warrant that + * we'll preserve the line timings for 30 fps, no matter what resolution + * is selected. + */ + + hstart = 14 + (640 - core->width) / 2; + mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); + mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); + mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); + + vstart = 8 + (640 - core->height) / 2; + mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); + mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); + mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); +}; + static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) { - u16 version; int i; - version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); - - if (version != MT9V011_VERSION) { - v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", - version); - return -EINVAL; - - } - for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) mt9v011_write(sd, mt9v011_init_default[i].reg, mt9v011_init_default[i].value); set_balance(sd); + set_res(sd); return 0; }; @@ -250,6 +260,50 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } +static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) +{ + if (fmt->index > 0) + return -EINVAL; + + fmt->flags = 0; + strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); + fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; + + return 0; +} + +static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) + return -EINVAL; + + v4l_bound_align_image(&pix->width, 48, 639, 1, + &pix->height, 32, 480, 1, 0); + + return 0; +} + +static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + struct mt9v011 *core = to_mt9v011(sd); + int rc; + + rc = mt9v011_try_fmt(sd, fmt); + if (rc < 0) + return -EINVAL; + + core->width = pix->width; + core->height = pix->height; + + set_res(sd); + + return 0; +} + + #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v011_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -303,8 +357,15 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { #endif }; +static const struct v4l2_subdev_video_ops mt9v011_video_ops = { + .enum_fmt = mt9v011_enum_fmt, + .try_fmt = mt9v011_try_fmt, + .s_fmt = mt9v011_s_fmt, +}; + static const struct v4l2_subdev_ops mt9v011_ops = { - .core = &mt9v011_core_ops, + .core = &mt9v011_core_ops, + .video = &mt9v011_video_ops, }; @@ -315,6 +376,7 @@ static const struct v4l2_subdev_ops mt9v011_ops = { static int mt9v011_probe(struct i2c_client *c, const struct i2c_device_id *id) { + u16 version; struct mt9v011 *core; struct v4l2_subdev *sd; @@ -327,10 +389,22 @@ static int mt9v011_probe(struct i2c_client *c, if (!core) return -ENOMEM; - core->global_gain = 0x0024; - sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); + + /* Check if the sensor is really a MT9V011 */ + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + if (version != MT9V011_VERSION) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + version); + kfree(core); + return -EINVAL; + } + + core->global_gain = 0x0024; + core->width = 640; + core->height = 480; + v4l_info(c, "chip found @ 0x%02x (%s)\n", c->addr << 1, c->adapter->name); -- GitLab From 6934e6fface7b7d5fe7e578c3f43cbe8f23af2d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Sat, 4 Jul 2009 08:15:11 -0300 Subject: [PATCH 0742/1002] V4L/DVB (12174): mt9v011: let's stick with datasheet values where it works The original driver for Silvercrest cameras were using some values that are different from what datasheet says. As result, it was taken very less snapshots per second than expected. A test with the datasheet values showed that they work fine and give a better frame rate. So, let's stick with datasheet values. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/mt9v011.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index 3ed9511da8edc..1fe8fc9183a77 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -124,24 +124,12 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, - { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, - { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, + { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, + + { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, - { R20_MT9V011_READ_MODE, 0x1100 }, - - /* - * Those registers are not docummented at the datasheet. - * However, the original driver initializes them - */ - { 0x30, 0x0005 }, - { 0x34, 0x0100 }, - { 0x3d, 0x068f }, - { 0x40, 0x01e0 }, - { 0x52, 0x0100 }, - { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ - { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ - { 0x62, 0x041a }, /* Datasheet default 0x0418 */ + { R20_MT9V011_READ_MODE, 0x1000 }, { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ }; @@ -177,6 +165,9 @@ static void set_res(struct v4l2_subdev *sd) * hblank and vblank should be adjusted, in order to warrant that * we'll preserve the line timings for 30 fps, no matter what resolution * is selected. + * NOTE: datasheet says that width (and height) should be filled with + * width-1. However, this doesn't work, since one pixel per line will + * be missing. */ hstart = 14 + (640 - core->width) / 2; -- GitLab From 02e7804b2135ff941b8846f5820cf48fbfdadd54 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Mon, 29 Jun 2009 11:35:05 -0300 Subject: [PATCH 0743/1002] V4L/DVB (12138): em28xx: add support for Silvercrest Webcam This webcam uses a em2710 chipset, that identifies itself as em2820, plus a mt9v011 sensor, and a DY-301P lens. It needs a few different initializations than a normal em28xx device. Thanks to Hans de Goede <hdegoede@redhat.com> and Douglas Landgraf <dougsland@redhat.com> for providing the acces for the webcam during this weekend, I could make a patch for it while returning back from FISL/Fudcom LATAM 2009. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/Kconfig | 2 ++ drivers/media/video/em28xx/em28xx-cards.c | 37 ++++++++++++++++++++++- drivers/media/video/em28xx/em28xx-core.c | 33 ++++++++++++++++---- drivers/media/video/em28xx/em28xx.h | 3 ++ 5 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 873630e7e53eb..014d255231fc7 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -66,3 +66,4 @@ 68 -> Terratec AV350 (em2860) [0ccd:0084] 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313] 70 -> Evga inDtube (em2882) + 71 -> Silvercrest Webcam 1.3mpix (em2820/em2840) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 16a5af30e9d1f..6524b493e033e 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -8,6 +8,8 @@ config VIDEO_EM28XX select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO + ---help--- This is a video4linux driver for Empia 28xx based TV cards. diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c43fdb9bc8881..bd9b637c7ea55 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -191,6 +191,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, { -1, -1, -1, -1}, }; + +static struct em28xx_reg_seq silvercrest_reg_seq[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, + { -1, -1, -1, -1}, +}; + /* * Board definitions */ @@ -438,6 +445,18 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2820_BOARD_SILVERCREST_WEBCAM] = { + .name = "Silvercrest Webcam 1.3mpix", + .tuner_type = TUNER_ABSENT, + .is_27xx = 1, + .decoder = EM28XX_MT9V011, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = silvercrest_reg_seq, + } }, + }, [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1639,6 +1658,11 @@ static unsigned short tvp5150_addrs[] = { I2C_CLIENT_END }; +static unsigned short mt9v011_addrs[] = { + 0xba >> 1, + I2C_CLIENT_END +}; + static unsigned short msp3400_addrs[] = { 0x80 >> 1, 0x88 >> 1, @@ -1706,7 +1730,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820\n"); + if (dev->board.is_27xx) + em28xx_info("chip is em2710\n"); + else + em28xx_info("chip ID is em2820\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); @@ -2158,6 +2185,10 @@ void em28xx_card_setup(struct em28xx *dev) before probing the i2c bus. */ em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; + case EM2820_BOARD_SILVERCREST_WEBCAM: + /* FIXME: need to document the registers bellow */ + em28xx_write_reg(dev, 0x0d, 0x42); + em28xx_write_reg(dev, 0x13, 0x08); } if (dev->board.has_snapshot_button) @@ -2189,6 +2220,10 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvp5150", "tvp5150", tvp5150_addrs); + if (dev->board.decoder == EM28XX_MT9V011) + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9v011", "mt9v011", mt9v011_addrs); + if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvaudio", "tvaudio", dev->board.tvaudio_addr); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c8d7ce8fbd368..dda2721ee5b08 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -648,17 +648,29 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_set_outfmt(struct em28xx *dev) { int ret; + int vinmode, vinctl, outfmt; + + outfmt = dev->format->reg; + + if (dev->board.is_27xx) { + vinmode = 0x0d; + vinctl = 0x00; + outfmt = 0x24; + } else { + vinmode = 0x10; + vinctl = 0x11; + } ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - dev->format->reg | 0x20, 0x3f); + outfmt | 0x20, 0xff); if (ret < 0) - return ret; + return ret; - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); if (ret < 0) return ret; - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -695,13 +707,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->board.is_em2800) + + if (dev->board.is_27xx) { + /* FIXME: Don't use the scaler yet */ + mode = 0; + } else if (dev->board.is_em2800) { mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); - else { + } else { u8 buf[2]; + buf[0] = h; buf[1] = h >> 8; em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); + buf[0] = v; buf[1] = v >> 8; em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); @@ -720,8 +738,11 @@ int em28xx_resolution_set(struct em28xx *dev) height = norm_maxh(dev) >> 1; em28xx_set_outfmt(dev); + + em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 813ce45c2f997..d90fef4637646 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -107,6 +107,7 @@ #define EM2860_BOARD_TERRATEC_AV350 68 #define EM2882_BOARD_KWORLD_ATSC_315U 69 #define EM2882_BOARD_EVGA_INDTUBE 70 +#define EM2820_BOARD_SILVERCREST_WEBCAM 71 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -360,6 +361,7 @@ enum em28xx_decoder { EM28XX_NODECODER, EM28XX_TVP5150, EM28XX_SAA711X, + EM28XX_MT9V011, }; enum em28xx_adecoder { @@ -388,6 +390,7 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; + unsigned int is_27xx:1; unsigned int valid:1; unsigned char xclk, i2c_speed; -- GitLab From 43cb9fe3291bb96390c1d188eb61c2d1581bb61e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Tue, 30 Jun 2009 08:36:17 -0300 Subject: [PATCH 0744/1002] V4L/DVB (12139): em28xx: add other video formats Add suppport for the teste RGB565 format (16 bits/pixel). Currently, webcam support works only at RGB565, at 640x480. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-video.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8fe1beecfffac..b96a138d9d03b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -94,6 +94,11 @@ static struct em28xx_fmt format[] = { .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, + }, { + .name = "16 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB565, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV211, }, }; @@ -694,6 +699,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -701,7 +710,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_em2800) { + if (dev->board.is_27xx) { + /* FIXME: This is the only supported fmt */ + width = 640; + height = 480; + } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; @@ -747,6 +760,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + vidioc_try_fmt_vid_cap(file, priv, f); fmt = format_by_fourcc(f->fmt.pix.pixelformat); -- GitLab From f797608cc4f19b44b83ec39c87e14af6fa07826d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller <dheitmueller@kernellabs.com> Date: Mon, 22 Jun 2009 22:32:32 -0300 Subject: [PATCH 0745/1002] V4L/DVB (12156): em28xx: Fix tuning for Terratec Cinergy T XS USB (zl10353 version) Fix the code so that the zl10353 version of the Terratec Cinergy T XS USB starts working again. This includes fixing what must have been a typo in the GPIO definition for the digital side of the board, and setting of the disable_i2c_gate_ctrl property for the zl10353 config, so that the i2c bus doesn't get wedged the first time something tries to close the gate. Also, add a printk() making clear that the mt352 version still isn't supported. This issue is still being actively debugged, but in the meantime at least the dmesg output will show a very clear error... Thanks to Jelle de Jong for providing sample hardware to test with. Thanks to Simon Kenyon for testing various patches and providing SSH access to his environment so I could debug with access to a valid signal source. Cc: Jelle de Jong <jelledejong@powercraft.nl> Cc: Simon Kenyon <simon@koala.ie> Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-dvb.c | 28 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index bd9b637c7ea55..01fbb7d2e5690 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -845,7 +845,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, - .dvb_gpio = default_analog, + .dvb_gpio = default_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index e7b47c8da8f3e..3da97c32b8fad 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -243,6 +243,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, + .parallel_ts = 1, + .if2 = 45600, +}; + #ifdef EM28XX_DRX397XD_SUPPORT /* [TODO] djh - not sure yet what the device config needs to contain */ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { @@ -433,7 +441,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_KWORLD_DVB_310U: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, @@ -444,6 +451,25 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2880_BOARD_TERRATEC_HYBRID_XS: + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_terratec_xs_zl10353_xc3028, + &dev->i2c_adap); + if (dvb->frontend == NULL) { + /* This board could have either a zl10353 or a mt352. + If the chip id isn't for zl10353, try mt352 */ + + /* FIXME: make support for mt352 work */ + printk(KERN_ERR "version of this board with mt352 not " + "currently supported\n"); + result = -EINVAL; + goto out_free; + } + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->frontend = dvb_attach(s5h1409_attach, -- GitLab From ed5f1431ebeeba8cc6739e9cd905a7895b66184c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Thu, 2 Jul 2009 17:34:04 -0300 Subject: [PATCH 0746/1002] V4L/DVB (12169): em28xx-video: fix VIDIOC_G_FMT and VIDIOC_ENUMFMT with webcams Webcams have different constraints than other v4l devices. This patch makes the format ioctls to behave better. It also fixes a bug at open() handler, that were always reseting resolution to the maximum available one. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-video.c | 79 ++++++++++++++--------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index b96a138d9d03b..702fe8d6742e5 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -746,13 +746,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, + unsigned width, unsigned height) +{ + struct em28xx_fmt *fmt; + + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) { + fourcc = V4L2_PIX_FMT_RGB565; + width = 640; + height = 480; + } + + fmt = format_by_fourcc(fourcc); + if (!fmt) + return -EINVAL; + + dev->format = fmt; + dev->width = width; + dev->height = height; + + /* set new image size */ + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + em28xx_set_alternate(dev); + em28xx_resolution_set(dev); + + return 0; +} + static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; - struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -760,18 +788,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - vidioc_try_fmt_vid_cap(file, priv, f); - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - rc = -EINVAL; - goto out; - } - if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -784,16 +802,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - /* set new image size */ - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - dev->format = fmt; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - rc = 0; + rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, + f->fmt.pix.width, f->fmt.pix.height); out: mutex_unlock(&dev->lock); @@ -1377,9 +1387,24 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; + if (dev->board.is_27xx) { + struct em28xx_fmt *fmt; + if (f->index) + return -EINVAL; + + f->pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->pixelformat); + strlcpy(f->description, fmt->name, sizeof(f->description)); + + return 0; + } + strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; @@ -1633,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) filp->private_data = fh; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->hscale = 0; - dev->vscale = 0; - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_alternate(dev); em28xx_resolution_set(dev); @@ -1979,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* set default norm */ dev->norm = em28xx_video_template.current_norm; - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; dev->ctl_input = 0; /* Analog specific initialization */ dev->format = &format[0]; + em28xx_set_video_format(dev, format[0].fourcc, + norm_maxw(dev), norm_maxh(dev)); + video_mux(dev, dev->ctl_input); /* Audio defaults */ -- GitLab From 557dca5f48a45df88a73e69ee0700cfd4e2358c9 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sun, 5 Jul 2009 22:39:08 +0100 Subject: [PATCH 0747/1002] [ARM] amba: fix amba device resources AMBA device resources were being reported as: 10004000-10004fff : <BAD> This is because dev_name() was returning NULL prior to device_register. Ensure that the struct device is properly initialized, and the name is set before adding it to the device tree. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- drivers/amba/bus.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 3d763fdf99b7d..2466506730105 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -207,6 +207,16 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) void __iomem *tmp; int i, ret; + device_initialize(&dev->dev); + + /* + * Copy from device_add + */ + if (dev->dev.init_name) { + dev_set_name(&dev->dev, "%s", dev->dev.init_name); + dev->dev.init_name = NULL; + } + dev->dev.release = amba_device_release; dev->dev.bus = &amba_bustype; dev->dev.dma_mask = &dev->dma_mask; @@ -240,7 +250,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) goto err_release; } - ret = device_register(&dev->dev); + ret = device_add(&dev->dev); if (ret) goto err_release; -- GitLab From 58fc1ce37aba8e6371e1ec8a90d650b1965ee6c8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Fri, 3 Jul 2009 02:54:18 -0300 Subject: [PATCH 0748/1002] V4L/DVB (12171): em28xx: fix webcam usage with different output formats Discovered the bug that were limiting the output format to just RGB565. Now, it is possible to output image at Bayer format (the original one, as generated by Silvercrest sensor, and two others), and also on YUY. Adds Bayer formats also to the driver. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-core.c | 1 - drivers/media/video/em28xx/em28xx-video.c | 46 +++++++++++------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index dda2721ee5b08..079ab4d563a62 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -655,7 +655,6 @@ int em28xx_set_outfmt(struct em28xx *dev) if (dev->board.is_27xx) { vinmode = 0x0d; vinctl = 0x00; - outfmt = 0x24; } else { vinmode = 0x10; vinctl = 0x11; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 702fe8d6742e5..14316c912179a 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -90,15 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct em28xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", + .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, }, { - .name = "16 bpp RGB, le", + .name = "16 bpp RGB 565, LE", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, - .reg = EM28XX_OUTFMT_YUV211, + .reg = EM28XX_OUTFMT_RGB_16_656, + }, { + .name = "8 bpp Bayer BGBG..GRGR", + .fourcc = V4L2_PIX_FMT_SBGGR8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, + }, { + .name = "8 bpp Bayer GRGR..BGBG", + .fourcc = V4L2_PIX_FMT_SGRBG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GRGR, + }, { + .name = "8 bpp Bayer GBGB..RGRG", + .fourcc = V4L2_PIX_FMT_SGBRG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, + }, { + .name = "12 bpp YUV411", + .fourcc = V4L2_PIX_FMT_YUV411P, + .depth = 12, + .reg = EM28XX_OUTFMT_YUV411, }, }; @@ -699,10 +719,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -753,7 +769,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, /* FIXME: This is the only supported fmt */ if (dev->board.is_27xx) { - fourcc = V4L2_PIX_FMT_RGB565; width = 640; height = 480; } @@ -1387,24 +1402,9 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - if (dev->board.is_27xx) { - struct em28xx_fmt *fmt; - if (f->index) - return -EINVAL; - - f->pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->pixelformat); - strlcpy(f->description, fmt->name, sizeof(f->description)); - - return 0; - } - strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; -- GitLab From 791a08fc01aaa293a73c9dce260327fdee288faf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Fri, 3 Jul 2009 15:36:18 -0300 Subject: [PATCH 0749/1002] V4L/DVB (12172): em28xx: Add autodetection code for Silvercrest 1.3 mpix Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-cards.c | 44 +++++++++++++++++++++++ drivers/media/video/em28xx/em28xx-i2c.c | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 01fbb7d2e5690..8366c521921dc 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -58,6 +58,8 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); +#define MT9V011_VERSION 0x8243 + /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; @@ -1702,6 +1704,46 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } +/* HINT method: webcam I2C chips + * + * This method work for webcams with Micron sensors + */ +static int em28xx_hint_sensor(struct em28xx *dev) +{ + int rc; + char *sensor_name; + unsigned char cmd; + __be16 version_be; + u16 version; + + if (dev->model != EM2820_BOARD_UNKNOWN) + return 0; + + dev->i2c_client.addr = 0xba >> 1; + cmd = 0; + i2c_master_send(&dev->i2c_client, &cmd, 1); + rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); + if (rc != 2) + return -EINVAL; + + version = be16_to_cpu(version_be); + + switch (version) { + case MT9V011_VERSION: + dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; + sensor_name = "mt9v011"; + break; + default: + printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); + return -EINVAL; + } + + em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", + sensor_name, em28xx_boards[dev->model].name); + + return 0; +} + /* Since em28xx_pre_card_setup() requires a proper dev->model, * this won't work for boards with generic PCI IDs */ @@ -2368,6 +2410,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } + em28xx_hint_sensor(dev); + /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2c86fcf089f59..27e33a287dfc8 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -483,7 +483,7 @@ static char *i2c_devs[128] = { [0xa0 >> 1] = "eeprom", [0xb0 >> 1] = "tda9874", [0xb8 >> 1] = "tvp5150a", - [0xba >> 1] = "tvp5150a", + [0xba >> 1] = "webcam sensor or tvp5150a", [0xc0 >> 1] = "tuner (analog)", [0xc2 >> 1] = "tuner (analog)", [0xc4 >> 1] = "tuner (analog)", -- GitLab From 11b79ea75ada39b7f1efdebdad520c93c3ac1f0e Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Sun, 5 Jul 2009 14:06:41 -0300 Subject: [PATCH 0750/1002] V4L/DVB (12202): em28xx, fix lock imbalance There is one omitted unlock in em28xx_usb_probe. Fix that. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Douglas Schilling Landgraf <dougsland@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 8366c521921dc..ebd24a25fb851 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2652,6 +2652,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { em28xx_devused &= ~(1<<dev->devno); + mutex_unlock(&dev->lock); kfree(dev); goto err; } -- GitLab From a5ca3a1bc719cb9056acc6f24340a1e2674f21a0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Sun, 5 Jul 2009 15:44:20 -0300 Subject: [PATCH 0751/1002] V4L/DVB (12203): radio-si470x: fix lock imbalance There is one path with omitted unlock in si470x_fops_release. Fix that. Cc: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Douglas Schilling Landgraf <dougsland@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/radio/radio-si470x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 640421ceb24a2..46d2163296113 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1200,7 +1200,7 @@ static int si470x_fops_release(struct file *file) video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); - goto done; + goto unlock; } /* stop rds reception */ @@ -1213,9 +1213,8 @@ static int si470x_fops_release(struct file *file) retval = si470x_stop(radio); usb_autopm_put_interface(radio->intf); } - +unlock: mutex_unlock(&radio->disconnect_lock); - done: return retval; } -- GitLab From 0a6843483c256c859cd9542361812a29403f0fb5 Mon Sep 17 00:00:00 2001 From: Andy Walls <awalls@radix.net> Date: Sun, 5 Jul 2009 16:22:45 -0300 Subject: [PATCH 0752/1002] V4L/DVB (12206): get_dvb_firmware: Correct errors in MPC718 firmware extraction logic The extraction routine for the MPC718 "firmware" had 2 bugs in it, where one bug masked the effect of the other. The loop iteration should have set $prevlen = $currlen at the end of the loop, and the if() check should have used && instead of || for deciding if the firmware length is reasonable. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/dvb/get_dvb_firmware | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 64174d6258f01..3d1b0ab70c8ef 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -413,13 +413,14 @@ sub mpc718 { while (<IN>) { $currlen = length($_); - if ($prevlen == $currlen || $currlen <= 64) { + if ($prevlen == $currlen && $currlen <= 64) { chop; chop; # Get rid of "TUNER GO" s/^\0\0//; # get rid of leading 00 00 if it's there printf OUT "$_"; $found = 1; last; } + $prevlen = $currlen; } } close OUT; -- GitLab From d23e43658aed286b885d398ff0810f04f6aae97f Mon Sep 17 00:00:00 2001 From: Herbert Xu <herbert@gondor.apana.org.au> Date: Thu, 2 Jul 2009 23:03:55 +0000 Subject: [PATCH 0753/1002] tun: Fix device unregister race It is currently possible for an asynchronous device unregister to cause the same tun device to be unregistered twice. This is because the unregister in tun_chr_close only checks whether __tun_get(tfile) != NULL. This however has nothing to do with whether the device has already been unregistered. All it tells you is whether __tun_detach has been called. This patch fixes this by using the most obvious thing to test whether the device has been unregistered. It also moves __tun_detach outside of rtnl_unlock since nothing that it does requires that lock. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/tun.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 11a0ba47b6778..b393536012fb3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1324,20 +1324,22 @@ static int tun_chr_close(struct inode *inode, struct file *file) struct tun_file *tfile = file->private_data; struct tun_struct *tun; - - rtnl_lock(); tun = __tun_get(tfile); if (tun) { - DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); + struct net_device *dev = tun->dev; + + DBG(KERN_INFO "%s: tun_chr_close\n", dev->name); __tun_detach(tun); /* If desireable, unregister the netdevice. */ - if (!(tun->flags & TUN_PERSIST)) - unregister_netdevice(tun->dev); - + if (!(tun->flags & TUN_PERSIST)) { + rtnl_lock(); + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(dev); + rtnl_unlock(); + } } - rtnl_unlock(); tun = tfile->tun; if (tun) -- GitLab From 3799cf47e3497a472b05f88e7a52a14931597d78 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein <eilong@broadcom.com> Date: Sun, 5 Jul 2009 04:18:12 +0000 Subject: [PATCH 0754/1002] bnx2x: Disable HC coalescing when setting timeout to zero. Problem reported by Flavio Leitner <fleitner@redhat.com>: When setting rx/tx coalescing timeout to the values less than 12 traffic was stopped. The FW supports coalescing in 12us granularity, and so value of less then 12 should be interpreted as disabling coalescing Signed-off-by: Vlad Zolotarov <vladz@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 951714a7f90a8..5737b7519005d 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4434,7 +4434,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR16(bp, BAR_USTRORM_INTMEM + USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, U_SB_ETH_RX_CQ_INDEX), - bp->rx_ticks ? 0 : 1); + (bp->rx_ticks/12) ? 0 : 1); /* HC_INDEX_C_ETH_TX_CQ_CONS */ REG_WR8(bp, BAR_CSTRORM_INTMEM + @@ -4444,7 +4444,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp) REG_WR16(bp, BAR_CSTRORM_INTMEM + CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, C_SB_ETH_TX_CQ_INDEX), - bp->tx_ticks ? 0 : 1); + (bp->tx_ticks/12) ? 0 : 1); } } -- GitLab From 1e9d9987598fa58f4bd8e72ee152c879136d6723 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein <eilong@broadcom.com> Date: Sun, 5 Jul 2009 04:18:14 +0000 Subject: [PATCH 0755/1002] bnx2x: Fix the maximal values of coalescing timeouts. This patch properly defines the maximum values for rx/tx coalescing timeouts. Signed-off-by: Vlad Zolotarov <vladz@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/bnx2x.h | 2 ++ drivers/net/bnx2x_main.c | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 8678457849f9f..85a737c5c23f2 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -902,6 +902,8 @@ struct bnx2x { u16 rx_quick_cons_trip; u16 rx_ticks_int; u16 rx_ticks; +/* Maximal coalescing timeout in us */ +#define BNX2X_MAX_COALESCE_TOUT (0xf0*12) u32 lin_cnt; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 5737b7519005d..6c67be679764d 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9069,12 +9069,12 @@ static int bnx2x_set_coalesce(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); bp->rx_ticks = (u16) coal->rx_coalesce_usecs; - if (bp->rx_ticks > 3000) - bp->rx_ticks = 3000; + if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT; bp->tx_ticks = (u16) coal->tx_coalesce_usecs; - if (bp->tx_ticks > 0x3000) - bp->tx_ticks = 0x3000; + if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT) + bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT; if (netif_running(dev)) bnx2x_update_coalesce(bp); -- GitLab From 4c3dd308adbda61f2ab46a14a0adcca8e1338ea5 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki <ken_kawasaki@spring.nifty.jp> Date: Sat, 4 Jul 2009 14:17:10 +0000 Subject: [PATCH 0756/1002] pcnet_cs: add new id add new id (RIOS System PC CARD3 ETHERNET). Signed-off-by: Ken Kawasaki <ken_kawasaki@spring.nifty.jp> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/pcmcia/pcnet_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 652a368883612..9ef1c1bfa83d3 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826), PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), -- GitLab From 3942453948015228d6b1ae9835a6f6ca3e842aaa Mon Sep 17 00:00:00 2001 From: Julia Lawall <julia@diku.dk> Date: Sat, 4 Jul 2009 11:31:47 +0000 Subject: [PATCH 0757/1002] drivers/net/smsc911x.c: Fix resource size off by 1 error The call resource_size(res) returns res->end - res->start + 1 and thus the second change is semantics-preserving. res_size is then used as the second argument of a call to request_mem_region, and the memory allocated by this call appears to be the same as what is released in the two calls to release_mem_region. So the size argument for those calls should be resource_size(size) as well. Alternatively, in the second call to release_mem_region, the second argument could be res_size, as that variable has already been initialized at the point of this call. The problem was found using the following semantic patch: (http://www.emn.fr/x-info/coccinelle/) // <smpl> @@ struct resource *res; @@ - (res->end - res->start) + 1 + resource_size(res) @@ struct resource *res; @@ - res->end - res->start + BAD(resource_size(res)) // </smpl> Signed-off-by: Julia Lawall <julia@diku.dk> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/smsc911x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b60639bd181b9..66067f9d91c05 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1938,7 +1938,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) if (!res) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); iounmap(pdata->ioaddr); @@ -1976,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) retval = -ENODEV; goto out_0; } - res_size = res->end - res->start + 1; + res_size = resource_size(res); irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { @@ -2104,7 +2104,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) out_free_netdev_2: free_netdev(dev); out_release_io_1: - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); out_0: return retval; } -- GitLab From 78c29bd95bd8d2c3bcf7932cb3ab8ae01cd8f58f Mon Sep 17 00:00:00 2001 From: Eric Dumazet <eric.dumazet@gmail.com> Date: Thu, 2 Jul 2009 04:04:45 +0000 Subject: [PATCH 0758/1002] forcedeth: Fix NAPI race. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eric Dumazet a écrit : > Ingo Molnar a écrit : >>> The following changes since commit 52989765629e7d182b4f146050ebba0abf2cb0b7: >>> Linus Torvalds (1): >>> Merge git://git.kernel.org/.../davem/net-2.6 >>> >>> are available in the git repository at: >>> >>> master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git master >> Hm, something in this lot quickly wrecked networking here - see the >> tx timeout dump below. It starts with: >> >> [ 351.004596] WARNING: at net/sched/sch_generic.c:246 dev_watchdog+0x10b/0x19c() >> [ 351.011815] Hardware name: System Product Name >> [ 351.016220] NETDEV WATCHDOG: eth0 (forcedeth): transmit queue 0 timed out >> >> Config attached. Unfortunately i've got no time to do bisection >> today. > > > > forcedeth might have a problem, in its netif_wake_queue() logic, but > I could not see why a recent patch could make this problem visible now. > > CPU0/1: AMD Athlon(tm) 64 X2 Dual Core Processor 3800+ stepping 02 > is not a new cpu either :) > > forcedeth uses an internal tx_stop without appropriate barrier. > > Could you try following patch ? > > (random guess as I dont have much time right now) We might have a race in napi_schedule(), leaving interrupts disabled forever. I cannot test this patch, I dont have the hardware... Tested-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/forcedeth.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 1094d292630f7..3b4e0766c7b2a 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3514,11 +3514,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - napi_schedule(&np->napi); - - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); + if (napi_schedule_prep(&np->napi)) { + /* + * Disable further irq's (msix not enabled with napi) + */ + writel(0, base + NvRegIrqMask); + __napi_schedule(&np->napi); + } #else do @@ -3615,12 +3617,13 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) nv_msi_workaround(np); #ifdef CONFIG_FORCEDETH_NAPI - napi_schedule(&np->napi); - - /* Disable furthur irq's - (msix not enabled with napi) */ - writel(0, base + NvRegIrqMask); - + if (napi_schedule_prep(&np->napi)) { + /* + * Disable further irq's (msix not enabled with napi) + */ + writel(0, base + NvRegIrqMask); + __napi_schedule(&np->napi); + } #else do { -- GitLab From 1ded3f59f35a2642852b3e2a1c0fa8a97777e9af Mon Sep 17 00:00:00 2001 From: Stephane Contri <Stephane.Contri@grassvalley.com> Date: Thu, 2 Jul 2009 23:26:48 +0000 Subject: [PATCH 0759/1002] dsa: fix 88e6xxx statistics counter snapshotting The bit that tells us whether a statistics counter snapshot operation has completed is located in the GLOBAL register block, not in the GLOBAL2 register block, so fix up mv88e6xxx_stats_wait() to poll the right register address. Signed-off-by: Stephane Contri <Stephane.Contri@grassvalley.com> Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Cc: stable@kernel.org Signed-off-by: David S. Miller <davem@davemloft.net> --- net/dsa/mv88e6xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/mv88e6xxx.c b/net/dsa/mv88e6xxx.c index 4e4d8b5ad03d3..efe661a9def4d 100644 --- a/net/dsa/mv88e6xxx.c +++ b/net/dsa/mv88e6xxx.c @@ -418,7 +418,7 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds) int i; for (i = 0; i < 10; i++) { - ret = REG_READ(REG_GLOBAL2, 0x1d); + ret = REG_READ(REG_GLOBAL, 0x1d); if ((ret & 0x8000) == 0) return 0; } -- GitLab From 81d8279ea31a3fc6d4ffacd87119a04c561ca62e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 18 Jun 2009 19:55:27 +0200 Subject: [PATCH 0760/1002] microblaze: fall back on generic header files for the ABI Almost all of the ABI relevant header files now have generic versions, so use those now in order to reduce the amount of architecture specific code. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/ioctls.h | 92 +--------- arch/microblaze/include/asm/ipcbuf.h | 37 +--- arch/microblaze/include/asm/mman.h | 24 --- arch/microblaze/include/asm/msgbuf.h | 32 +--- arch/microblaze/include/asm/param.h | 31 +--- arch/microblaze/include/asm/posix_types.h | 68 +------- arch/microblaze/include/asm/sembuf.h | 35 +--- arch/microblaze/include/asm/shmbuf.h | 43 +---- arch/microblaze/include/asm/siginfo.h | 14 -- arch/microblaze/include/asm/socket.h | 70 +------- arch/microblaze/include/asm/sockios.h | 24 +-- arch/microblaze/include/asm/stat.h | 69 +------- arch/microblaze/include/asm/swab.h | 9 +- arch/microblaze/include/asm/termbits.h | 204 +--------------------- arch/microblaze/include/asm/termios.h | 89 +--------- arch/microblaze/include/asm/types.h | 39 +---- arch/microblaze/include/asm/ucontext.h | 23 +-- 17 files changed, 16 insertions(+), 887 deletions(-) diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h index 03582b2492047..ec34c760665ea 100644 --- a/arch/microblaze/include/asm/ioctls.h +++ b/arch/microblaze/include/asm/ioctls.h @@ -1,91 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_IOCTLS_H -#define _ASM_MICROBLAZE_IOCTLS_H - -#include <linux/ioctl.h> - -/* 0x54 is just a magic number to make these relatively unique ('T') */ - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 -#define TCGETA 0x5405 -#define TCSETA 0x5406 -#define TCSETAW 0x5407 -#define TCSETAF 0x5408 -#define TCSBRK 0x5409 -#define TCXONC 0x540A -#define TCFLSH 0x540B -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E -#define TIOCGPGRP 0x540F -#define TIOCSPGRP 0x5410 -#define TIOCOUTQ 0x5411 -#define TIOCSTI 0x5412 -#define TIOCGWINSZ 0x5413 -#define TIOCSWINSZ 0x5414 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define FIONREAD 0x541B -#define TIOCINQ FIONREAD -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 -#define FIONBIO 0x5421 -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TIOCSBRK 0x5427 /* BSD compatibility */ -#define TIOCCBRK 0x5428 /* BSD compatibility */ -#define TIOCGSID 0x5429 /* Return the session ID of FD */ -/* Get Pty Number (of pty-mux device) */ -#define TIOCGPTN _IOR('T', 0x30, unsigned int) -#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ - -#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ -#define FIOCLEX 0x5451 -#define FIOASYNC 0x5452 -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - -#define FIOQSIZE 0x545E - -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#endif /* _ASM_MICROBLAZE_IOCTLS_H */ +#include <asm-generic/ioctls.h> diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h index b056fa4206544..84c7e51cb6d0b 100644 --- a/arch/microblaze/include/asm/ipcbuf.h +++ b/arch/microblaze/include/asm/ipcbuf.h @@ -1,36 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_IPCBUF_H -#define _ASM_MICROBLAZE_IPCBUF_H - -/* - * The user_ipc_perm structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 32-bit mode_t and seq - * - 2 miscellaneous 32-bit values - */ - -struct ipc64_perm { - __kernel_key_t key; - __kernel_uid32_t uid; - __kernel_gid32_t gid; - __kernel_uid32_t cuid; - __kernel_gid32_t cgid; - __kernel_mode_t mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* _ASM_MICROBLAZE_IPCBUF_H */ +#include <asm-generic/ipcbuf.h> diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h index 4914b1329445e..8eebf89f5ab17 100644 --- a/arch/microblaze/include/asm/mman.h +++ b/arch/microblaze/include/asm/mman.h @@ -1,25 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_MMAN_H -#define _ASM_MICROBLAZE_MMAN_H - #include <asm-generic/mman.h> - -#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ -#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ -#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ -#define MAP_LOCKED 0x2000 /* pages are locked */ -#define MAP_NORESERVE 0x4000 /* don't check for reservations */ -#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -#define MCL_CURRENT 1 /* lock all current mappings */ -#define MCL_FUTURE 2 /* lock all future mappings */ - -#endif /* _ASM_MICROBLAZE_MMAN_H */ diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h index 09dd97097211c..809134c644a67 100644 --- a/arch/microblaze/include/asm/msgbuf.h +++ b/arch/microblaze/include/asm/msgbuf.h @@ -1,31 +1 @@ -#ifndef _ASM_MICROBLAZE_MSGBUF_H -#define _ASM_MICROBLAZE_MSGBUF_H - -/* - * The msqid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct msqid64_ds { - struct ipc64_perm msg_perm; - __kernel_time_t msg_stime; /* last msgsnd time */ - unsigned long __unused1; - __kernel_time_t msg_rtime; /* last msgrcv time */ - unsigned long __unused2; - __kernel_time_t msg_ctime; /* last change time */ - unsigned long __unused3; - unsigned long msg_cbytes; /* current number of bytes on queue */ - unsigned long msg_qnum; /* number of messages in queue */ - unsigned long msg_qbytes; /* max number of bytes on queue */ - __kernel_pid_t msg_lspid; /* pid of last msgsnd */ - __kernel_pid_t msg_lrpid; /* last receive pid */ - unsigned long __unused4; - unsigned long __unused5; -}; - -#endif /* _ASM_MICROBLAZE_MSGBUF_H */ +#include <asm-generic/msgbuf.h> diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h index 8c538a49616d8..965d454279759 100644 --- a/arch/microblaze/include/asm/param.h +++ b/arch/microblaze/include/asm/param.h @@ -1,30 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_PARAM_H -#define _ASM_MICROBLAZE_PARAM_H - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ /* internal kernel timer frequency */ -#define USER_HZ 100 /* for user interfaces in "ticks" */ -#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ -#endif /* __KERNEL__ */ - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* _ASM_MICROBLAZE_PARAM_H */ +#include <asm-generic/param.h> diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h index 8c758b231f376..0e15039673e34 100644 --- a/arch/microblaze/include/asm/posix_types.h +++ b/arch/microblaze/include/asm/posix_types.h @@ -1,73 +1,9 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - #ifndef _ASM_MICROBLAZE_POSIX_TYPES_H #define _ASM_MICROBLAZE_POSIX_TYPES_H -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc. Also, we cannot - * assume GCC is being used. - */ - -typedef unsigned long __kernel_ino_t; typedef unsigned short __kernel_mode_t; -typedef unsigned int __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned int __kernel_ipc_pid_t; -typedef unsigned int __kernel_uid_t; -typedef unsigned int __kernel_gid_t; -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef int __kernel_daddr_t; -typedef char *__kernel_caddr_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned int __kernel_old_uid_t; -typedef unsigned int __kernel_old_gid_t; -typedef unsigned int __kernel_old_dev_t; - -#ifdef __GNUC__ -typedef long long __kernel_loff_t; -#endif - -typedef struct { -#if defined(__KERNEL__) || defined(__USE_ALL) - int val[2]; -#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ - int __val[2]; -#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ -} __kernel_fsid_t; - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) - -#undef __FD_SET -#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) - -#undef __FD_CLR -#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) - -#undef __FD_ISSET -#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d))) - -#undef __FD_ZERO -#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp))) +#define __kernel_mode_t __kernel_mode_t -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#include <asm-generic/posix_types.h> #endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */ diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h index b804ed71a57e5..7673b83cfef73 100644 --- a/arch/microblaze/include/asm/sembuf.h +++ b/arch/microblaze/include/asm/sembuf.h @@ -1,34 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SEMBUF_H -#define _ASM_MICROBLAZE_SEMBUF_H - -/* - * The semid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct semid64_ds { - struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ - __kernel_time_t sem_otime; /* last semop time */ - unsigned long __unused1; - __kernel_time_t sem_ctime; /* last change time */ - unsigned long __unused2; - unsigned long sem_nsems; /* no. of semaphores in array */ - unsigned long __unused3; - unsigned long __unused4; -}; - - -#endif /* _ASM_MICROBLAZE_SEMBUF_H */ +#include <asm-generic/sembuf.h> diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h index f829c58436185..83c05fc2de385 100644 --- a/arch/microblaze/include/asm/shmbuf.h +++ b/arch/microblaze/include/asm/shmbuf.h @@ -1,42 +1 @@ -#ifndef _ASM_MICROBLAZE_SHMBUF_H -#define _ASM_MICROBLAZE_SHMBUF_H - -/* - * The shmid64_ds structure for microblaze architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 64-bit time_t to solve y2038 problem - * - 2 miscellaneous 32-bit values - */ - -struct shmid64_ds { - struct ipc64_perm shm_perm; /* operation perms */ - size_t shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - unsigned long __unused1; - __kernel_time_t shm_dtime; /* last detach time */ - unsigned long __unused2; - __kernel_time_t shm_ctime; /* last change time */ - unsigned long __unused3; - __kernel_pid_t shm_cpid; /* pid of creator */ - __kernel_pid_t shm_lpid; /* pid of last operator */ - unsigned long shm_nattch; /* no. of current attaches */ - unsigned long __unused4; - unsigned long __unused5; -}; - -struct shminfo64 { - unsigned long shmmax; - unsigned long shmmin; - unsigned long shmmni; - unsigned long shmseg; - unsigned long shmall; - unsigned long __unused1; - unsigned long __unused2; - unsigned long __unused3; - unsigned long __unused4; -}; - -#endif /* _ASM_MICROBLAZE_SHMBUF_H */ +#include <asm-generic/shmbuf.h> diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h index f162911a8f50c..0815d29d82e5f 100644 --- a/arch/microblaze/include/asm/siginfo.h +++ b/arch/microblaze/include/asm/siginfo.h @@ -1,15 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SIGINFO_H -#define _ASM_MICROBLAZE_SIGINFO_H - -#include <linux/types.h> #include <asm-generic/siginfo.h> - -#endif /* _ASM_MICROBLAZE_SIGINFO_H */ diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h index 8259368603149..6b71384b9d8b4 100644 --- a/arch/microblaze/include/asm/socket.h +++ b/arch/microblaze/include/asm/socket.h @@ -1,69 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SOCKET_H -#define _ASM_MICROBLAZE_SOCKET_H - -#include <asm/sockios.h> - -/* For setsockoptions(2) */ -#define SOL_SOCKET 1 - -#define SO_DEBUG 1 -#define SO_REUSEADDR 2 -#define SO_TYPE 3 -#define SO_ERROR 4 -#define SO_DONTROUTE 5 -#define SO_BROADCAST 6 -#define SO_SNDBUF 7 -#define SO_RCVBUF 8 -#define SO_SNDBUFFORCE 32 -#define SO_RCVBUFFORCE 33 -#define SO_KEEPALIVE 9 -#define SO_OOBINLINE 10 -#define SO_NO_CHECK 11 -#define SO_PRIORITY 12 -#define SO_LINGER 13 -#define SO_BSDCOMPAT 14 -/* To add :#define SO_REUSEPORT 15 */ -#define SO_PASSCRED 16 -#define SO_PEERCRED 17 -#define SO_RCVLOWAT 18 -#define SO_SNDLOWAT 19 -#define SO_RCVTIMEO 20 -#define SO_SNDTIMEO 21 - -/* Security levels - as per NRL IPv6 - don't actually do anything */ -#define SO_SECURITY_AUTHENTICATION 22 -#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 -#define SO_SECURITY_ENCRYPTION_NETWORK 24 - -#define SO_BINDTODEVICE 25 - -/* Socket filtering */ -#define SO_ATTACH_FILTER 26 -#define SO_DETACH_FILTER 27 - -#define SO_PEERNAME 28 -#define SO_TIMESTAMP 29 -#define SCM_TIMESTAMP SO_TIMESTAMP - -#define SO_ACCEPTCONN 30 - -#define SO_PEERSEC 31 -#define SO_PASSSEC 34 - -#define SO_TIMESTAMPNS 35 -#define SCM_TIMESTAMPNS SO_TIMESTAMPNS - -#define SO_MARK 36 - -#define SO_TIMESTAMPING 37 -#define SCM_TIMESTAMPING SO_TIMESTAMPING - -#endif /* _ASM_MICROBLAZE_SOCKET_H */ +#include <asm-generic/socket.h> diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h index 9fff57a701e1e..def6d4746ee7f 100644 --- a/arch/microblaze/include/asm/sockios.h +++ b/arch/microblaze/include/asm/sockios.h @@ -1,23 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SOCKIOS_H -#define _ASM_MICROBLAZE_SOCKIOS_H - -#include <linux/ioctl.h> - -/* Socket-level I/O control calls. */ -#define FIOSETOWN 0x8901 -#define SIOCSPGRP 0x8902 -#define FIOGETOWN 0x8903 -#define SIOCGPGRP 0x8904 -#define SIOCATMARK 0x8905 -#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ -#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ - -#endif /* _ASM_MICROBLAZE_SOCKIOS_H */ +#include <asm-generic/sockios.h> diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h index a15f77520bfd7..3dc90fa92c704 100644 --- a/arch/microblaze/include/asm/stat.h +++ b/arch/microblaze/include/asm/stat.h @@ -1,68 +1 @@ -/* - * Microblaze stat structure - * - * Copyright (C) 2001,02,03 NEC Electronics Corporation - * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -#ifndef _ASM_MICROBLAZE_STAT_H -#define _ASM_MICROBLAZE_STAT_H - -#include <linux/posix_types.h> - -#define STAT_HAVE_NSEC 1 - -struct stat { - unsigned long st_dev; - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long st_rdev; - unsigned long __pad1; - long st_size; - int st_blksize; - int __pad2; - long st_blocks; - int st_atime; - unsigned int st_atime_nsec; - int st_mtime; - unsigned int st_mtime_nsec; - int st_ctime; - unsigned int st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; -}; - -struct stat64 { - unsigned long long st_dev; /* Device. */ - unsigned long long st_ino; /* File serial number. */ - unsigned int st_mode; /* File mode. */ - unsigned int st_nlink; /* Link count. */ - unsigned int st_uid; /* User ID of the file's owner. */ - unsigned int st_gid; /* Group ID of the file's group. */ - unsigned long long st_rdev; /* Device number, if device. */ - unsigned long long __pad1; - long long st_size; /* Size of file, in bytes. */ - int st_blksize; /* Optimal block size for I/O. */ - int __pad2; - long long st_blocks; /* Number 512-byte blocks allocated. */ - int st_atime; /* Time of last access. */ - unsigned int st_atime_nsec; - int st_mtime; /* Time of last modification. */ - unsigned int st_mtime_nsec; - int st_ctime; /* Time of last status change. */ - unsigned int st_ctime_nsec; - unsigned int __unused4; - unsigned int __unused5; -}; - -#endif /* _ASM_MICROBLAZE_STAT_H */ - +#include <asm-generic/stat.h> diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h index b375d7b65ad73..7847e563ab66f 100644 --- a/arch/microblaze/include/asm/swab.h +++ b/arch/microblaze/include/asm/swab.h @@ -1,8 +1 @@ -#ifndef _ASM_MICROBLAZE_SWAB_H -#define _ASM_MICROBLAZE_SWAB_H - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) -#define __SWAB_64_THRU_32__ -#endif - -#endif /* _ASM_MICROBLAZE_SWAB_H */ +#include <asm-generic/swab.h> diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h index a1b64bc4724ac..3935b106de79b 100644 --- a/arch/microblaze/include/asm/termbits.h +++ b/arch/microblaze/include/asm/termbits.h @@ -1,203 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TERMBITS_H -#define _ASM_MICROBLAZE_TERMBITS_H - -#include <linux/posix_types.h> - -typedef unsigned char cc_t; -typedef unsigned int speed_t; -typedef unsigned int tcflag_t; - -#define NCCS 19 -struct termios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ -}; - -struct ktermios { - tcflag_t c_iflag; /* input mode flags */ - tcflag_t c_oflag; /* output mode flags */ - tcflag_t c_cflag; /* control mode flags */ - tcflag_t c_lflag; /* local mode flags */ - cc_t c_line; /* line discipline */ - cc_t c_cc[NCCS]; /* control characters */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -}; - -/* c_cc characters */ - -#define VINTR 0 -#define VQUIT 1 -#define VERASE 2 -#define VKILL 3 -#define VEOF 4 -#define VTIME 5 -#define VMIN 6 -#define VSWTC 7 -#define VSTART 8 -#define VSTOP 9 -#define VSUSP 10 -#define VEOL 11 -#define VREPRINT 12 -#define VDISCARD 13 -#define VWERASE 14 -#define VLNEXT 15 -#define VEOL2 16 - -/* c_iflag bits */ - -#define IGNBRK 0000001 -#define BRKINT 0000002 -#define IGNPAR 0000004 -#define PARMRK 0000010 -#define INPCK 0000020 -#define ISTRIP 0000040 -#define INLCR 0000100 -#define IGNCR 0000200 -#define ICRNL 0000400 -#define IUCLC 0001000 -#define IXON 0002000 -#define IXANY 0004000 -#define IXOFF 0010000 -#define IMAXBEL 0020000 -#define IUTF8 0040000 - -/* c_oflag bits */ - -#define OPOST 0000001 -#define OLCUC 0000002 -#define ONLCR 0000004 -#define OCRNL 0000010 -#define ONOCR 0000020 -#define ONLRET 0000040 -#define OFILL 0000100 -#define OFDEL 0000200 -#define NLDLY 0000400 -#define NL0 0000000 -#define NL1 0000400 -#define CRDLY 0003000 -#define CR0 0000000 -#define CR1 0001000 -#define CR2 0002000 -#define CR3 0003000 -#define TABDLY 0014000 -#define TAB0 0000000 -#define TAB1 0004000 -#define TAB2 0010000 -#define TAB3 0014000 -#define XTABS 0014000 -#define BSDLY 0020000 -#define BS0 0000000 -#define BS1 0020000 -#define VTDLY 0040000 -#define VT0 0000000 -#define VT1 0040000 -#define FFDLY 0100000 -#define FF0 0000000 -#define FF1 0100000 - -/* c_cflag bit meaning */ - -#define CBAUD 0010017 -#define B0 0000000 /* hang up */ -#define B50 0000001 -#define B75 0000002 -#define B110 0000003 -#define B134 0000004 -#define B150 0000005 -#define B200 0000006 -#define B300 0000007 -#define B600 0000010 -#define B1200 0000011 -#define B1800 0000012 -#define B2400 0000013 -#define B4800 0000014 -#define B9600 0000015 -#define B19200 0000016 -#define B38400 0000017 -#define EXTA B19200 -#define EXTB B38400 -#define CSIZE 0000060 -#define CS5 0000000 -#define CS6 0000020 -#define CS7 0000040 -#define CS8 0000060 -#define CSTOPB 0000100 -#define CREAD 0000200 -#define PARENB 0000400 -#define PARODD 0001000 -#define HUPCL 0002000 -#define CLOCAL 0004000 -#define CBAUDEX 0010000 -#define B57600 0010001 -#define B115200 0010002 -#define B230400 0010003 -#define B460800 0010004 -#define B500000 0010005 -#define B576000 0010006 -#define B921600 0010007 -#define BOTHER 0010000 -#define B1000000 0010010 -#define B1152000 0010011 -#define B1500000 0010012 -#define B2000000 0010013 -#define B2500000 0010014 -#define B3000000 0010015 -#define B3500000 0010016 -#define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ -#define CMSPAR 010000000000 /* mark or space (stick) parity */ -#define CRTSCTS 020000000000 /* flow control */ - -#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ - -/* c_lflag bits */ - -#define ISIG 0000001 -#define ICANON 0000002 -#define XCASE 0000004 -#define ECHO 0000010 -#define ECHOE 0000020 -#define ECHOK 0000040 -#define ECHONL 0000100 -#define NOFLSH 0000200 -#define TOSTOP 0000400 -#define ECHOCTL 0001000 -#define ECHOPRT 0002000 -#define ECHOKE 0004000 -#define FLUSHO 0010000 -#define PENDIN 0040000 -#define IEXTEN 0100000 - -/* tcflow() and TCXONC use these */ - -#define TCOOFF 0 -#define TCOON 1 -#define TCIOFF 2 -#define TCION 3 - -/* tcflush() and TCFLSH use these */ - -#define TCIFLUSH 0 -#define TCOFLUSH 1 -#define TCIOFLUSH 2 - -/* tcsetattr uses these */ - -#define TCSANOW 0 -#define TCSADRAIN 1 -#define TCSAFLUSH 2 - -#endif /* _ASM_MICROBLAZE_TERMBITS_H */ +#include <asm-generic/termbits.h> diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h index 47a46d1fbe26f..280d78a9d9663 100644 --- a/arch/microblaze/include/asm/termios.h +++ b/arch/microblaze/include/asm/termios.h @@ -1,88 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TERMIOS_H -#define _ASM_MICROBLAZE_TERMIOS_H - -#include <linux/string.h> -#include <asm/termbits.h> -#include <asm/ioctls.h> - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -#ifdef __KERNEL__ -/* intr=^C quit=^| erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" -#endif - -/* Modem lines */ - -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -/* Line disciplines */ - -#define N_TTY 0 -#define N_SLIP 1 -#define N_MOUSE 2 -#define N_PPP 3 -#define N_STRIP 4 -#define N_AX25 5 -#define N_X25 6 /* X.25 async */ -#define N_6PACK 7 -#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */ -#define N_R3964 9 /* Reserved for Simatic R3964 module */ -#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */ -#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ -#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards - about SMS messages */ -#define N_HDLC 13 /* synchronous HDLC */ -#define N_SYNC_PPP 14 -#define N_HCI 15 /* Bluetooth HCI UART */ - -#ifdef __KERNEL__ - -#include <asm-generic/termios-base.h> - -#endif /* __KERNEL__ */ - -#endif /* _ASM_MICROBLAZE_TERMIOS_H */ +#include <asm-generic/termios.h> diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h index bebc018318f55..b9e79bc580dd6 100644 --- a/arch/microblaze/include/asm/types.h +++ b/arch/microblaze/include/asm/types.h @@ -1,38 +1 @@ -/* - * Copyright (C) Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_TYPES_H -#define _ASM_MICROBLAZE_TYPES_H - -/* - * This file is never included by application software unless - * explicitly requested (e.g., via linux/types.h) in which case the - * application is Linux specific so (user-) name space pollution is - * not a major issue. However, for interoperability, libraries still - * need to be careful to avoid a name clashes. - */ - -#include <asm-generic/int-ll64.h> - -# ifndef __ASSEMBLY__ - -typedef unsigned short umode_t; - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -# ifdef __KERNEL__ -# define BITS_PER_LONG 32 - -/* Dma addresses are 32-bits wide. */ - -typedef u32 dma_addr_t; - -# endif/* __KERNEL__ */ -# endif /* __ASSEMBLY__ */ -#endif /* _ASM_MICROBLAZE_TYPES_H */ +#include <asm-generic/types.h> diff --git a/arch/microblaze/include/asm/ucontext.h b/arch/microblaze/include/asm/ucontext.h index 11f6bb3ae3a4e..9bc07b9f30fba 100644 --- a/arch/microblaze/include/asm/ucontext.h +++ b/arch/microblaze/include/asm/ucontext.h @@ -1,22 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_UCONTEXT_H -#define _ASM_MICROBLAZE_UCONTEXT_H - -#include <asm/sigcontext.h> - -struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ -}; - -#endif /* _ASM_MICROBLAZE_UCONTEXT_H */ +#include <asm-generic/ucontext.h> -- GitLab From 14f8738976991d2f8fb6ab6e10e9003562c3d6bb Mon Sep 17 00:00:00 2001 From: Remis Lima Baima <remis.developer@googlemail.com> Date: Thu, 18 Jun 2009 19:55:32 +0200 Subject: [PATCH 0761/1002] microblaze: use the generic lib/checksum.c The microblaze checksum code is mostly identical to the asm-generic+lib version, so use that instead. Signed-off-by: Remis Lima Baima <remis.developer@googlemail.com> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/Kconfig | 3 + arch/microblaze/include/asm/checksum.h | 70 +--------- arch/microblaze/lib/Makefile | 2 +- arch/microblaze/lib/checksum.c | 172 ------------------------- 4 files changed, 6 insertions(+), 241 deletions(-) delete mode 100644 arch/microblaze/lib/checksum.c diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index b50b845fdd506..2db722d80d4d1 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -53,6 +53,9 @@ config GENERIC_HARDIRQS_NO__DO_IRQ config GENERIC_GPIO def_bool y +config GENERIC_CSUM + def_bool y + config PCI def_bool n diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h index 97ea46b5cf80a..128bf03b54b7e 100644 --- a/arch/microblaze/include/asm/checksum.h +++ b/arch/microblaze/include/asm/checksum.h @@ -10,12 +10,11 @@ #ifndef _ASM_MICROBLAZE_CHECKSUM_H #define _ASM_MICROBLAZE_CHECKSUM_H -#include <linux/in6.h> - /* * computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ +#define csum_tcpudp_nofold csum_tcpudp_nofold static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) @@ -30,71 +29,6 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, return sum; } -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -extern __wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * the same as csum_partial, but copies from src while it - * checksums - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -extern __wsum csum_partial_copy(const void *src, void *dst, int len, - __wsum sum); - -/* - * the same as csum_partial_copy, but copies from user space. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err); - -#define csum_partial_copy_nocheck(src, dst, len, sum) \ - csum_partial_copy((src), (dst), (len), (sum)) - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - * - */ -extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); - -/* - * Fold a partial checksum - */ -static inline __sum16 csum_fold(__wsum csum) -{ - u32 sum = (__force u32)csum; - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return (__force __sum16)~sum; -} - -static inline __sum16 -csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, - unsigned short proto, __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -extern __sum16 ip_compute_csum(const void *buff, int len); +#include <asm-generic/checksum.h> #endif /* _ASM_MICROBLAZE_CHECKSUM_H */ diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index 71c8cb6c9e437..b579db068c06f 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -2,7 +2,7 @@ # Makefile # -lib-y := memset.o checksum.o +lib-y := memset.o ifeq ($(CONFIG_OPT_LIB_ASM),y) lib-y += fastcopy.o diff --git a/arch/microblaze/lib/checksum.c b/arch/microblaze/lib/checksum.c deleted file mode 100644 index f08e74591418d..0000000000000 --- a/arch/microblaze/lib/checksum.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, <jorge@laser.satlink.net> - * Arnt Gulbrandsen, <agulbra@nvg.unit.no> - * Tom May, <ftom@netcom.com> - * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: - * Fixed some nasty bugs, causing some horrible crashes. - * A: At some points, the sum (%0) was used as - * length-counter instead of the length counter - * (%1). Thanks to Roman Hodek for pointing this out. - * B: GCC seems to mess up if one uses too many - * data-registers to hold input values and one tries to - * specify d0 and d1 as scratch registers. Letting gcc - * choose these registers itself solves the problem. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access - kills, so most of the assembly has to go. */ - -#include <linux/module.h> -#include <net/checksum.h> - -#include <asm/byteorder.h> - -static inline unsigned short from32to16(unsigned long x) -{ - /* add up 16-bit and 16-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static unsigned int do_csum(const unsigned char *buff, int len) -{ - int odd, count; - unsigned long result = 0; - - if (len <= 0) - goto out; - odd = 1 & (unsigned long) buff; - if (odd) { - result = *buff; - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - count--; - buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffff) + (result >> 16); - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += (*buff << 8); - result = from32to16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); -out: - return result; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -__sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - return (__force __sum16)~do_csum(iph, ihl*4); -} -EXPORT_SYMBOL(ip_fast_csum); - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -__wsum csum_partial(const void *buff, int len, __wsum wsum) -{ - unsigned int sum = (__force unsigned int)wsum; - unsigned int result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - if (sum > result) - result += 1; - return (__force __wsum)result; -} -EXPORT_SYMBOL(csum_partial); - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -__sum16 ip_compute_csum(const void *buff, int len) -{ - return (__force __sum16)~do_csum(buff, len); -} -EXPORT_SYMBOL(ip_compute_csum); - -/* - * copy from fs while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *csum_err) -{ - int missing; - - missing = __copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *csum_err = -EFAULT; - } else - *csum_err = 0; - - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy_from_user); - -/* - * copy from ds while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy(const void *src, void *dst, int len, __wsum sum) -{ - memcpy(dst, src, len); - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy); -- GitLab From 0a58458341fd571e521be542ff746a4a8995980c Mon Sep 17 00:00:00 2001 From: Remis Lima Baima <remis.developer@googlemail.com> Date: Thu, 18 Jun 2009 19:55:33 +0200 Subject: [PATCH 0762/1002] microblaze: convert all simple headers to use asm-generic All the simple microblaze header files were adapted to use their asm-generic implementations. These files are more simple and were quite straightforward to change. fb.h, vga.h and parport.h previously did not exist, using the generic version makes it possible to build more drivers successfully in allyesonfig. Signed-off-by: Remis Lima Baima <remis.developer@googlemail.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/atomic.h | 101 +------------------ arch/microblaze/include/asm/bitops.h | 26 ----- arch/microblaze/include/asm/bug.h | 14 --- arch/microblaze/include/asm/bugs.h | 18 +--- arch/microblaze/include/asm/fb.h | 1 + arch/microblaze/include/asm/hardirq.h | 14 +-- arch/microblaze/include/asm/irq.h | 6 +- arch/microblaze/include/asm/mmu.h | 7 +- arch/microblaze/include/asm/mmu_context.h | 2 +- arch/microblaze/include/asm/mmu_context_no.h | 23 ----- arch/microblaze/include/asm/module.h | 10 +- arch/microblaze/include/asm/parport.h | 1 + arch/microblaze/include/asm/pci.h | 2 +- arch/microblaze/include/asm/scatterlist.h | 29 +----- arch/microblaze/include/asm/serial.h | 15 +-- arch/microblaze/include/asm/shmparam.h | 7 +- arch/microblaze/include/asm/system.h | 3 + arch/microblaze/include/asm/timex.h | 6 +- arch/microblaze/include/asm/vga.h | 2 +- 19 files changed, 21 insertions(+), 266 deletions(-) create mode 100644 arch/microblaze/include/asm/fb.h delete mode 100644 arch/microblaze/include/asm/mmu_context_no.h create mode 100644 arch/microblaze/include/asm/parport.h diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 0de612ad7cb2e..6d2e1d418be74 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h @@ -1,95 +1,7 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - #ifndef _ASM_MICROBLAZE_ATOMIC_H #define _ASM_MICROBLAZE_ATOMIC_H -#include <linux/types.h> -#include <linux/compiler.h> /* likely */ -#include <asm/system.h> /* local_irq_XXX and friends */ - -#define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) -#define atomic_set(v, i) (((v)->counter) = (i)) - -#define atomic_inc(v) (atomic_add_return(1, (v))) -#define atomic_dec(v) (atomic_sub_return(1, (v))) - -#define atomic_add(i, v) (atomic_add_return(i, (v))) -#define atomic_sub(i, v) (atomic_sub_return(i, (v))) - -#define atomic_inc_return(v) (atomic_add_return(1, (v))) -#define atomic_dec_return(v) (atomic_sub_return(1, (v))) - -#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) -#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) - -#define atomic_inc_not_zero(v) (atomic_add_unless((v), 1, 0)) - -#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) - -static inline int atomic_cmpxchg(atomic_t *v, int old, int new) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (likely(ret == old)) - v->counter = new; - local_irq_restore(flags); - - return ret; -} - -static inline int atomic_add_unless(atomic_t *v, int a, int u) -{ - int c, old; - - c = atomic_read(v); - while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) - c = old; - return c != u; -} - -static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) -{ - unsigned long flags; - - local_irq_save(flags); - *addr &= ~mask; - local_irq_restore(flags); -} - -/** - * atomic_add_return - add and return - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v and returns @i + @v - */ -static inline int atomic_add_return(int i, atomic_t *v) -{ - unsigned long flags; - int val; - - local_irq_save(flags); - val = v->counter; - v->counter = val += i; - local_irq_restore(flags); - - return val; -} - -static inline int atomic_sub_return(int i, atomic_t *v) -{ - return atomic_add_return(-i, v); -} +#include <asm-generic/atomic.h> /* * Atomically test *v and decrement if it is greater than 0. @@ -109,15 +21,4 @@ static inline int atomic_dec_if_positive(atomic_t *v) return res; } -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - -/* Atomic operations are already serializing */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#include <asm-generic/atomic-long.h> - #endif /* _ASM_MICROBLAZE_ATOMIC_H */ diff --git a/arch/microblaze/include/asm/bitops.h b/arch/microblaze/include/asm/bitops.h index d6df1fd4e1e87..a72468f15c8b1 100644 --- a/arch/microblaze/include/asm/bitops.h +++ b/arch/microblaze/include/asm/bitops.h @@ -1,27 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BITOPS_H -#define _ASM_MICROBLAZE_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - */ - -#include <asm/byteorder.h> /* swab32 */ -#include <asm/system.h> /* save_flags */ - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() #include <asm-generic/bitops.h> -#include <asm-generic/bitops/__fls.h> - -#endif /* _ASM_MICROBLAZE_BITOPS_H */ diff --git a/arch/microblaze/include/asm/bug.h b/arch/microblaze/include/asm/bug.h index 8eb2cdde11d7c..b12fd89e42e91 100644 --- a/arch/microblaze/include/asm/bug.h +++ b/arch/microblaze/include/asm/bug.h @@ -1,15 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BUG_H -#define _ASM_MICROBLAZE_BUG_H - -#include <linux/kernel.h> #include <asm-generic/bug.h> - -#endif /* _ASM_MICROBLAZE_BUG_H */ diff --git a/arch/microblaze/include/asm/bugs.h b/arch/microblaze/include/asm/bugs.h index f2c6593653fb0..61791e1ad9f55 100644 --- a/arch/microblaze/include/asm/bugs.h +++ b/arch/microblaze/include/asm/bugs.h @@ -1,17 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_BUGS_H -#define _ASM_MICROBLAZE_BUGS_H - -static inline void check_bugs(void) -{ - /* nothing to do */ -} - -#endif /* _ASM_MICROBLAZE_BUGS_H */ +#include <asm-generic/bugs.h> diff --git a/arch/microblaze/include/asm/fb.h b/arch/microblaze/include/asm/fb.h new file mode 100644 index 0000000000000..3a4988e8df456 --- /dev/null +++ b/arch/microblaze/include/asm/fb.h @@ -0,0 +1 @@ +#include <asm-generic/fb.h> diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h index 0f2d6b013e11e..41e1e1aa36aca 100644 --- a/arch/microblaze/include/asm/hardirq.h +++ b/arch/microblaze/include/asm/hardirq.h @@ -9,21 +9,11 @@ #ifndef _ASM_MICROBLAZE_HARDIRQ_H #define _ASM_MICROBLAZE_HARDIRQ_H -#include <linux/cache.h> -#include <linux/irq.h> -#include <asm/irq.h> -#include <asm/current.h> -#include <linux/ptrace.h> - /* should be defined in each interrupt controller driver */ extern unsigned int get_irq(struct pt_regs *regs); -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - +#define ack_bad_irq ack_bad_irq void ack_bad_irq(unsigned int irq); - -#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ +#include <asm-generic/hardirq.h> #endif /* _ASM_MICROBLAZE_HARDIRQ_H */ diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index db515deaa720c..90f050535ebef 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -10,6 +10,7 @@ #define _ASM_MICROBLAZE_IRQ_H #define NR_IRQS 32 +#include <asm-generic/irq.h> #include <linux/interrupt.h> @@ -17,11 +18,6 @@ extern unsigned int nr_irq; #define NO_IRQ (-1) -static inline int irq_canonicalize(int irq) -{ - return irq; -} - struct pt_regs; extern void do_IRQ(struct pt_regs *regs); diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h index 66cad6a99d77b..8d6a654ceffb1 100644 --- a/arch/microblaze/include/asm/mmu.h +++ b/arch/microblaze/include/asm/mmu.h @@ -12,12 +12,7 @@ #define _ASM_MICROBLAZE_MMU_H # ifndef CONFIG_MMU -# ifndef __ASSEMBLY__ -typedef struct { - struct vm_list_struct *vmlist; - unsigned long end_brk; -} mm_context_t; -# endif /* __ASSEMBLY__ */ +# include <asm-generic/mmu.h> # else /* CONFIG_MMU */ # ifdef __KERNEL__ # ifndef __ASSEMBLY__ diff --git a/arch/microblaze/include/asm/mmu_context.h b/arch/microblaze/include/asm/mmu_context.h index 385fed16bbfb1..24eab1674d3ee 100644 --- a/arch/microblaze/include/asm/mmu_context.h +++ b/arch/microblaze/include/asm/mmu_context.h @@ -1,5 +1,5 @@ #ifdef CONFIG_MMU # include "mmu_context_mm.h" #else -# include "mmu_context_no.h" +# include <asm-generic/mmu_context.h> #endif diff --git a/arch/microblaze/include/asm/mmu_context_no.h b/arch/microblaze/include/asm/mmu_context_no.h deleted file mode 100644 index ba55671901548..0000000000000 --- a/arch/microblaze/include/asm/mmu_context_no.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> - * Copyright (C) 2008-2009 PetaLogix - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H -#define _ASM_MICROBLAZE_MMU_CONTEXT_H - -# define init_new_context(tsk, mm) ({ 0; }) - -# define enter_lazy_tlb(mm, tsk) do {} while (0) -# define change_mm_context(old, ctx, _pml4) do {} while (0) -# define destroy_context(mm) do {} while (0) -# define deactivate_mm(tsk, mm) do {} while (0) -# define switch_mm(prev, next, tsk) do {} while (0) -# define activate_mm(prev, next) do {} while (0) - -#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */ diff --git a/arch/microblaze/include/asm/module.h b/arch/microblaze/include/asm/module.h index 914565a903151..7be1347fce42c 100644 --- a/arch/microblaze/include/asm/module.h +++ b/arch/microblaze/include/asm/module.h @@ -9,6 +9,8 @@ #ifndef _ASM_MICROBLAZE_MODULE_H #define _ASM_MICROBLAZE_MODULE_H +#include <asm-generic/module.h> + /* Microblaze Relocations */ #define R_MICROBLAZE_NONE 0 #define R_MICROBLAZE_32 1 @@ -24,14 +26,6 @@ /* Keep this the last entry. */ #define R_MICROBLAZE_NUM 11 -struct mod_arch_specific { - int foo; -}; - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - typedef struct { volatile int counter; } module_t; #endif /* _ASM_MICROBLAZE_MODULE_H */ diff --git a/arch/microblaze/include/asm/parport.h b/arch/microblaze/include/asm/parport.h new file mode 100644 index 0000000000000..cf252af645908 --- /dev/null +++ b/arch/microblaze/include/asm/parport.h @@ -0,0 +1 @@ +#include <asm-generic/parport.h> diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index ca03794cf3f0e..9f0df5faf2c88 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -1 +1 @@ -#include <linux/io.h> +#include <asm-generic/pci.h> diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h index 08ff1d049b426..35d786fe93ae0 100644 --- a/arch/microblaze/include/asm/scatterlist.h +++ b/arch/microblaze/include/asm/scatterlist.h @@ -1,28 +1 @@ -/* - * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SCATTERLIST_H -#define _ASM_MICROBLAZE_SCATTERLIST_H - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - dma_addr_t dma_address; - unsigned int offset; - unsigned int length; -}; - -#define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->length) - -#define ISA_DMA_THRESHOLD (~0UL) - -#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */ +#include <asm-generic/scatterlist.h> diff --git a/arch/microblaze/include/asm/serial.h b/arch/microblaze/include/asm/serial.h index 39bfc8ce6af58..a0cb0caff1524 100644 --- a/arch/microblaze/include/asm/serial.h +++ b/arch/microblaze/include/asm/serial.h @@ -1,14 +1 @@ -/* - * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SERIAL_H -#define _ASM_MICROBLAZE_SERIAL_H - -# define BASE_BAUD (1843200 / 16) - -#endif /* _ASM_MICROBLAZE_SERIAL_H */ +#include <asm-generic/serial.h> diff --git a/arch/microblaze/include/asm/shmparam.h b/arch/microblaze/include/asm/shmparam.h index 9f5fc2b3b6a3c..93f30deb95d08 100644 --- a/arch/microblaze/include/asm/shmparam.h +++ b/arch/microblaze/include/asm/shmparam.h @@ -1,6 +1 @@ -#ifndef _ASM_MICROBLAZE_SHMPARAM_H -#define _ASM_MICROBLAZE_SHMPARAM_H - -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ - -#endif /* _ASM_MICROBLAZE_SHMPARAM_H */ +#include <asm-generic/shmparam.h> diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index c4e308850b5d6..b1ed615906600 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -13,6 +13,9 @@ #include <asm/setup.h> #include <asm/irqflags.h> +#include <asm-generic/cmpxchg.h> +#include <asm-generic/cmpxchg-local.h> + struct task_struct; struct thread_info; diff --git a/arch/microblaze/include/asm/timex.h b/arch/microblaze/include/asm/timex.h index 678525dc6d0b1..befcf3de5532c 100644 --- a/arch/microblaze/include/asm/timex.h +++ b/arch/microblaze/include/asm/timex.h @@ -9,10 +9,8 @@ #ifndef _ASM_MICROBLAZE_TIMEX_H #define _ASM_MICROBLAZE_TIMEX_H -#define CLOCK_TICK_RATE 1000 /* Timer input freq. */ - -typedef unsigned long cycles_t; +#include <asm-generic/timex.h> -#define get_cycles() (0) +#define CLOCK_TICK_RATE 1000 /* Timer input freq. */ #endif /* _ASM_TIMEX_H */ diff --git a/arch/microblaze/include/asm/vga.h b/arch/microblaze/include/asm/vga.h index 8b137891791fe..89d82fd8fcf17 100644 --- a/arch/microblaze/include/asm/vga.h +++ b/arch/microblaze/include/asm/vga.h @@ -1 +1 @@ - +#include <asm-generic/vga.h> -- GitLab From 3183e06863f49a500fc76427db4d60825a26f81b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 18 Jun 2009 19:55:29 +0200 Subject: [PATCH 0763/1002] microblaze: clean up signal handling When legacy signal handling is disabled, the arch/microblaze/kernel/signal.c implementation can be much simpler, as most of it is handled generically from kernel/signal.c. This is also a prerequisite for using the generic asm/unistd.h, which does not provide __NR_sigreturn, because this macro is referenced by the current signal.c implementation. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/signal.h | 166 +----------------------- arch/microblaze/include/asm/syscalls.h | 11 +- arch/microblaze/include/asm/unistd.h | 2 +- arch/microblaze/kernel/entry-nommu.S | 8 -- arch/microblaze/kernel/entry.S | 23 ---- arch/microblaze/kernel/signal.c | 172 ++++++------------------- arch/microblaze/kernel/syscall_table.S | 6 +- 7 files changed, 43 insertions(+), 345 deletions(-) diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h index 46bc2267d9497..7b1573ce19de5 100644 --- a/arch/microblaze/include/asm/signal.h +++ b/arch/microblaze/include/asm/signal.h @@ -1,165 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * Yasushi SHOJI <yashi@atmark-techno.com> - * Tetsuya OHKAWA <tetsuya@atmark-techno.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_SIGNAL_H -#define _ASM_MICROBLAZE_SIGNAL_H - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -# ifndef __ASSEMBLY__ -# include <linux/types.h> -# include <asm-generic/signal-defs.h> - -/* Avoid too many header ordering problems. */ -struct siginfo; - -# ifdef __KERNEL__ -/* - * Most things should be clean enough to redefine this at will, if care - * is taken to make libc match. - */ -# define _NSIG 64 -# define _NSIG_BPW 32 -# define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; - void (*sa_restorer)(void); - sigset_t sa_mask; /* mask last for extensibility */ -}; - -struct k_sigaction { - struct sigaction sa; -}; - -# include <asm/sigcontext.h> -# undef __HAVE_ARCH_SIG_BITOPS - -# define ptrace_signal_deliver(regs, cookie) do { } while (0) - -# else /* !__KERNEL__ */ - -/* Here we must cater to libcs that poke about in kernel headers. */ - -# define NSIG 32 -typedef unsigned long sigset_t; - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -# define sa_handler _u._sa_handler -# define sa_sigaction _u._sa_sigaction - -# endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -# endif /* __ASSEMBLY__ */ -#endif /* _ASM_MICROBLAZE_SIGNAL_H */ +#include <asm-generic/signal.h> diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h index ddea9eb31f8da..ea23843e2c26b 100644 --- a/arch/microblaze/include/asm/syscalls.h +++ b/arch/microblaze/include/asm/syscalls.h @@ -26,23 +26,16 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long fd, off_t offset); /* from signal.c */ -asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs); - -asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, +asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs); -asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact); - asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, size_t sigsetsize); asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs); -asmlinkage int sys_sigreturn(struct pt_regs *regs); - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); #endif /* __KERNEL__ */ #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index b5e2f5fa5c535..6c660c1446537 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -408,7 +408,7 @@ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION -/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */ +#define __ARCH_WANT_SYS_RT_SIGSUSPEND /* * "Conditional" syscalls diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 1fce6b803f549..2eaf3946cb42e 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -563,18 +563,10 @@ sys_execve_wrapper: brid sys_execve addk r8, r1, r0 -sys_sigreturn_wrapper: - brid sys_sigreturn - addk r5, r1, r0 - sys_rt_sigreturn_wrapper: brid sys_rt_sigreturn addk r5, r1, r0 -sys_sigsuspend_wrapper: - brid sys_rt_sigsuspend - addk r6, r1, r0 - sys_rt_sigsuspend_wrapper: brid sys_rt_sigsuspend addk r7, r1, r0 diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 91a0e7b185dd9..ea7107652d8d1 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -449,17 +449,6 @@ C_ENTRY(sys_execve_wrapper): brid sys_execve; /* Do real work (tail-call).*/ nop; -C_ENTRY(sys_sigsuspend_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r6, r1, PTO; /* add user context as 2nd arg */ - bralid r15, sys_sigsuspend; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; - C_ENTRY(sys_rt_sigsuspend_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; @@ -471,18 +460,6 @@ C_ENTRY(sys_rt_sigsuspend_wrapper): bri ret_from_trap /* fall through will not work here due to align */ nop; - -C_ENTRY(sys_sigreturn_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - la r5, r1, PTO; /* add user context as 1st arg */ - brlid r15, sys_sigreturn; /* Do real work.*/ - nop; - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; - C_ENTRY(sys_rt_sigreturn_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 4c0e6521b1140..2e5862c3002a7 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -45,89 +45,6 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r3 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset, 1)) - return -EINTR; - } -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->r3 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset, 1)) - return -EINTR; - } -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, @@ -139,7 +56,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ - struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; @@ -176,40 +92,7 @@ static int restore_sigcontext(struct pt_regs *regs, return err; } -asmlinkage int sys_sigreturn(struct pt_regs *regs) -{ - struct sigframe *frame = - (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE); - - sigset_t set; - int rval; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->sc, &rval)) - goto badframe; - return rval; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE); @@ -324,21 +207,17 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" */ - if (ka->sa.sa_flags & SA_RESTORER) { - regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; - } else { - /* addi r12, r0, __NR_sigreturn */ - err |= __put_user(0x31800000 | __NR_rt_sigreturn , - frame->tramp + 0); - /* brki r14, 0x8 */ - err |= __put_user(0xb9cc0008, frame->tramp + 1); - - /* Return from sighandler will jump to the tramp. - Negative 8 offset because return is rtsd r15, 8 */ - regs->r15 = ((unsigned long)frame->tramp)-8; - - __invalidate_cache_sigtramp((unsigned long)frame->tramp); - } + /* addi r12, r0, __NR_sigreturn */ + err |= __put_user(0x31800000 | __NR_rt_sigreturn , + frame->tramp + 0); + /* brki r14, 0x8 */ + err |= __put_user(0xb9cc0008, frame->tramp + 1); + + /* Return from sighandler will jump to the tramp. + Negative 8 offset because return is rtsd r15, 8 */ + regs->r15 = ((unsigned long)frame->tramp)-8; + + __invalidate_cache_sigtramp((unsigned long)frame->tramp); if (err) goto give_sigsegv; @@ -405,7 +284,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -426,6 +305,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } + return 1; } /* @@ -456,7 +336,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) if (kernel_mode(regs)) return 1; - if (!oldset) + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -464,13 +346,31 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ka, 1); - handle_signal(signr, &ka, &info, oldset, regs); + if (handle_signal(signr, &ka, &info, oldset, regs)) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= + ~TS_RESTORE_SIGMASK; + } return 1; } if (in_syscall) handle_restart(regs, NULL, 0); + /* + * If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + /* Did we come from a system call? */ return 0; } diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 376d1789f7c06..ef0e8932af33a 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -71,12 +71,12 @@ ENTRY(sys_call_table) .long sys_getppid .long sys_getpgrp /* 65 */ .long sys_setsid - .long sys_sigaction + .long sys_ni_syscall /* sys_sigaction */ .long sys_sgetmask .long sys_ssetmask .long sys_setreuid /* 70 */ .long sys_setregid - .long sys_sigsuspend_wrapper + .long sys_ni_syscall /* sys_sigsuspend_wrapper */ .long sys_sigpending .long sys_sethostname .long sys_setrlimit /* 75 */ @@ -123,7 +123,7 @@ ENTRY(sys_call_table) .long sys_sysinfo .long sys_ipc .long sys_fsync - .long sys_sigreturn_wrapper + .long sys_ni_syscall /* sys_sigreturn_wrapper */ .long sys_clone_wrapper /* 120 */ .long sys_setdomainname .long sys_newuname -- GitLab From e513588f75912f022677866244de6b19b98b8d9a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 18 Jun 2009 19:55:30 +0200 Subject: [PATCH 0764/1002] microblaze: use generic syscalls.h The prototypes in syscalls.h all make sense for microblaze, but for some of them, the actual implementation in sys_microblaze.c needs to be adapted. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/syscalls.h | 39 ++----------------------- arch/microblaze/kernel/entry-nommu.S | 12 ++++---- arch/microblaze/kernel/entry.S | 11 ++++--- arch/microblaze/kernel/signal.c | 2 +- arch/microblaze/kernel/sys_microblaze.c | 20 ++++++------- arch/microblaze/kernel/syscall_table.S | 6 ++-- 6 files changed, 28 insertions(+), 62 deletions(-) diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h index ea23843e2c26b..720761cc741f4 100644 --- a/arch/microblaze/include/asm/syscalls.h +++ b/arch/microblaze/include/asm/syscalls.h @@ -1,41 +1,8 @@ #ifndef __ASM_MICROBLAZE_SYSCALLS_H -#define __ASM_MICROBLAZE_SYSCALLS_H -#ifdef __KERNEL__ -#include <linux/compiler.h> -#include <linux/linkage.h> -#include <linux/types.h> -#include <linux/signal.h> +asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs); +#define sys_clone sys_clone -/* FIXME will be removed */ -asmlinkage int sys_ipc(uint call, int first, int second, - int third, void *ptr, long fifth); +#include <asm-generic/syscalls.h> -struct pt_regs; -asmlinkage int sys_vfork(struct pt_regs *regs); -asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs); -asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, - char __user *__user *envp, struct pt_regs *regs); - -asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff); - -asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset); - -/* from signal.c */ -asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, - struct pt_regs *regs); - -asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, - struct sigaction __user *oact, size_t sigsetsize); - -asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs); - -asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); - -#endif /* __KERNEL__ */ #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 2eaf3946cb42e..9083d85376a4d 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -551,16 +551,16 @@ no_work_pending: rtid r14, 0 nop -sys_vfork_wrapper: - brid sys_vfork +sys_vfork: + brid microblaze_vfork addk r5, r1, r0 -sys_clone_wrapper: - brid sys_clone +sys_clone: + brid microblaze_clone addk r7, r1, r0 -sys_execve_wrapper: - brid sys_execve +sys_execve: + brid microblaze_execve addk r8, r1, r0 sys_rt_sigreturn_wrapper: diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index ea7107652d8d1..c7353e79f4a22 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -429,12 +429,11 @@ C_ENTRY(ret_from_fork): brid ret_from_trap; /* Do normal trap return */ nop; -C_ENTRY(sys_vfork_wrapper): +C_ENTRY(sys_vfork): + brid microblaze_vfork /* Do real work (tail-call) */ la r5, r1, PTO - brid sys_vfork /* Do real work (tail-call) */ - nop -C_ENTRY(sys_clone_wrapper): +C_ENTRY(sys_clone): bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ lwi r6, r1, PTO+PT_R1; /* If so, use paret's stack ptr */ 1: la r7, r1, PTO; /* Arg 2: parent context */ @@ -444,9 +443,9 @@ C_ENTRY(sys_clone_wrapper): brid do_fork /* Do real work (tail-call) */ nop; -C_ENTRY(sys_execve_wrapper): +C_ENTRY(sys_execve): la r8, r1, PTO; /* add user context as 4th arg */ - brid sys_execve; /* Do real work (tail-call).*/ + brid microblaze_execve; /* Do real work (tail-call).*/ nop; C_ENTRY(sys_rt_sigsuspend_wrapper): diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 2e5862c3002a7..493819c25fbad 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -46,7 +46,7 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); -asmlinkage int +asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) { diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 31905ff590b70..8c9ebac5da10a 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -39,7 +39,7 @@ * * This is really horribly ugly. This will be remove with new toolchain. */ -asmlinkage int +asmlinkage long sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) { int version, ret; @@ -134,20 +134,20 @@ sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) return ret; } -asmlinkage int sys_vfork(struct pt_regs *regs) +asmlinkage long microblaze_vfork(struct pt_regs *regs) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, regs, 0, NULL, NULL); } -asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs) +asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs) { if (!stack) stack = regs->r1; return do_fork(flags, stack, regs, 0, NULL, NULL); } -asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, +asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv, char __user *__user *envp, struct pt_regs *regs) { int error; @@ -163,8 +163,8 @@ asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, return error; } -asmlinkage unsigned long -sys_mmap2(unsigned long addr, size_t len, +asmlinkage long +sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { @@ -189,18 +189,18 @@ sys_mmap2(unsigned long addr, size_t len, return ret; } -asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, +asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset) + unsigned long fd, off_t pgoff) { int err = -EINVAL; - if (offset & ~PAGE_MASK) { + if (pgoff & ~PAGE_MASK) { printk(KERN_INFO "no pagemask in mmap\r\n"); goto out; } - err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); out: return err; } diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index ef0e8932af33a..8a609354ddea5 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -15,7 +15,7 @@ ENTRY(sys_call_table) .long sys_creat .long sys_link .long sys_unlink /* 10 */ - .long sys_execve_wrapper + .long sys_execve .long sys_chdir .long sys_time .long sys_mknod @@ -124,7 +124,7 @@ ENTRY(sys_call_table) .long sys_ipc .long sys_fsync .long sys_ni_syscall /* sys_sigreturn_wrapper */ - .long sys_clone_wrapper /* 120 */ + .long sys_clone /* 120 */ .long sys_setdomainname .long sys_newuname .long sys_ni_syscall /* modify_ldt */ @@ -194,7 +194,7 @@ ENTRY(sys_call_table) .long sys_sendfile .long sys_ni_syscall /* reserved for streams1 */ .long sys_ni_syscall /* reserved for streams2 */ - .long sys_vfork_wrapper /* 190 */ + .long sys_vfork /* 190 */ .long sys_getrlimit .long sys_mmap2 /* mmap2 */ .long sys_truncate64 -- GitLab From 4ae78338157a1fe2d7a398d86bb9f9043d600d2b Mon Sep 17 00:00:00 2001 From: Michal Simek <monstr@monstr.eu> Date: Wed, 1 Jul 2009 15:32:14 +0200 Subject: [PATCH 0765/1002] microblaze: Wire up new syscalls Wire up new syscalls rt_tgsigqueueinfo and perf_counter_open. Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/unistd.h | 4 +++- arch/microblaze/kernel/syscall_table.S | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6c660c1446537..0b852327c0e7b 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -380,8 +380,10 @@ #define __NR_accept04 362 /* new */ #define __NR_preadv 363 /* new */ #define __NR_pwritev 364 /* new */ +#define __NR_rt_tgsigqueueinfo 365 /* new */ +#define __NR_perf_counter_open 366 /* new */ -#define __NR_syscalls 365 +#define __NR_syscalls 367 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 8a609354ddea5..31b32a6c5f4ee 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -369,3 +369,5 @@ ENTRY(sys_call_table) .long sys_ni_syscall .long sys_ni_syscall .long sys_ni_syscall + .long sys_rt_tgsigqueueinfo /* 365 */ + .long sys_perf_counter_open -- GitLab From db6e3f91efd2cf61b9965f722902199cf54adc4f Mon Sep 17 00:00:00 2001 From: Michal Simek <monstr@monstr.eu> Date: Mon, 6 Jul 2009 08:21:09 +0200 Subject: [PATCH 0766/1002] microblaze: Fix cast warning for init.c Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/mm/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index b5a701cd71e08..8d92c4efe9a4c 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -80,15 +80,15 @@ void __init setup_memory(void) memory_size = memory_end - memory_start; PAGE_OFFSET = memory_start; printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, " - "size 0x%08x\n", __func__, memory_start, - memory_end, memory_size); + "size 0x%08x\n", __func__, (u32) memory_start, + (u32) memory_end, (u32) memory_size); break; } } if (!memory_start || !memory_end) { panic("%s: Missing memory setting 0x%08x-0x%08x\n", - __func__, memory_start, memory_end); + __func__, (u32) memory_start, (u32) memory_end); } /* reservation of region where is the kernel */ -- GitLab From 3503e0acbfab0dbcd24ccadd5fe841f3f8290e81 Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Mon, 6 Jul 2009 12:39:27 -0700 Subject: [PATCH 0767/1002] Revert "ide: improve handling of Power Management requests" This reverts commit a1317f714af7aed60ddc182d0122477cbe36ee9b. --- drivers/ide/ide-io.c | 54 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d5f3c77beadd8..db96138fefcde 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -466,14 +466,10 @@ void do_ide_request(struct request_queue *q) if (!ide_lock_port(hwif)) { ide_hwif_t *prev_port; + + WARN_ON_ONCE(hwif->rq); repeat: prev_port = hwif->host->cur_port; - - if (drive->dev_flags & IDE_DFLAG_BLOCKED) - rq = hwif->rq; - else - WARN_ON_ONCE(hwif->rq); - if (drive->dev_flags & IDE_DFLAG_SLEEPING && time_after(drive->sleep, jiffies)) { ide_unlock_port(hwif); @@ -500,29 +496,43 @@ void do_ide_request(struct request_queue *q) hwif->cur_dev = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); - if (rq == NULL) { - spin_unlock_irq(&hwif->lock); - spin_lock_irq(q->queue_lock); - /* - * we know that the queue isn't empty, but this can - * happen if ->prep_rq_fn() decides to kill a request - */ + spin_unlock_irq(&hwif->lock); + spin_lock_irq(q->queue_lock); + /* + * we know that the queue isn't empty, but this can happen + * if the q->prep_rq_fn() decides to kill a request + */ + if (!rq) rq = blk_fetch_request(drive->queue); - spin_unlock_irq(q->queue_lock); - spin_lock_irq(&hwif->lock); - if (rq == NULL) { - ide_unlock_port(hwif); - goto out; - } + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwif->lock); + + if (!rq) { + ide_unlock_port(hwif); + goto out; } /* * Sanity: don't accept a request that isn't a PM request - * if we are currently power managed. + * if we are currently power managed. This is very important as + * blk_stop_queue() doesn't prevent the blk_fetch_request() + * above to return us whatever is in the queue. Since we call + * ide_do_request() ourselves, we end up taking requests while + * the queue is blocked... + * + * We let requests forced at head of queue with ide-preempt + * though. I hope that doesn't happen too much, hopefully not + * unless the subdriver triggers such a thing in its own PM + * state machine. */ - BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) && - blk_pm_request(rq) == 0); + if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && + blk_pm_request(rq) == 0 && + (rq->cmd_flags & REQ_PREEMPT) == 0) { + /* there should be no pending command at this point */ + ide_unlock_port(hwif); + goto plug_device; + } hwif->rq = rq; -- GitLab From 3c8a9c63d5fd738c261bd0ceece04d9c8357ca13 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Date: Sun, 5 Jul 2009 19:48:35 +0000 Subject: [PATCH 0768/1002] tun/tap: Fix crashes if open() /dev/net/tun and then poll() it. Fix NULL pointer dereference in tun_chr_pool() introduced by commit 33dccbb050bbe35b88ca8cf1228dcf3e4d4b3554 ("tun: Limit amount of queued packets per device") and triggered by this code: int fd; struct pollfd pfd; fd = open("/dev/net/tun", O_RDWR); pfd.fd = fd; pfd.events = POLLIN | POLLOUT; poll(&pfd, 1, 0); Reported-by: Eugene Kapun <abacabadabacaba@gmail.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/tun.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b393536012fb3..027f7aba26af1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { struct tun_file *tfile = file->private_data; struct tun_struct *tun = __tun_get(tfile); - struct sock *sk = tun->sk; + struct sock *sk; unsigned int mask = 0; if (!tun) return POLLERR; + sk = tun->sk; + DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); poll_wait(file, &tun->socket.wait, wait); -- GitLab From 1bc4ee4088c9a502db0e9c87f675e61e57fa1734 Mon Sep 17 00:00:00 2001 From: Wei Yongjun <yjwei@cn.fujitsu.com> Date: Sun, 5 Jul 2009 19:45:48 +0000 Subject: [PATCH 0769/1002] sctp: fix warning at inet_sock_destruct() while release sctp socket Commit 'net: Move rx skb_orphan call to where needed' broken sctp protocol with warning at inet_sock_destruct(). Actually, sctp can do this right with sctp_sock_rfree_frag() and sctp_skb_set_owner_r_frag() pair. sctp_sock_rfree_frag(skb); sctp_skb_set_owner_r_frag(skb, newsk); This patch not revert the commit d55d87fdff8252d0e2f7c28c2d443aee17e9d70f, instead remove the sctp_sock_rfree_frag() function. ------------[ cut here ]------------ WARNING: at net/ipv4/af_inet.c:151 inet_sock_destruct+0xe0/0x142() Modules linked in: sctp ipv6 dm_mirror dm_region_hash dm_log dm_multipath scsi_mod ext3 jbd uhci_hcd ohci_hcd ehci_hcd [last unloaded: scsi_wait_scan] Pid: 1808, comm: sctp_test Not tainted 2.6.31-rc2 #40 Call Trace: [<c042dd06>] warn_slowpath_common+0x6a/0x81 [<c064a39a>] ? inet_sock_destruct+0xe0/0x142 [<c042dd2f>] warn_slowpath_null+0x12/0x15 [<c064a39a>] inet_sock_destruct+0xe0/0x142 [<c05fde44>] __sk_free+0x19/0xcc [<c05fdf50>] sk_free+0x18/0x1a [<ca0d14ad>] sctp_close+0x192/0x1a1 [sctp] [<c0649f7f>] inet_release+0x47/0x4d [<c05fba4d>] sock_release+0x19/0x5e [<c05fbab3>] sock_close+0x21/0x25 [<c049c31b>] __fput+0xde/0x189 [<c049c3de>] fput+0x18/0x1a [<c049988f>] filp_close+0x56/0x60 [<c042f422>] put_files_struct+0x5d/0xa1 [<c042f49f>] exit_files+0x39/0x3d [<c043086a>] do_exit+0x1a5/0x5dd [<c04a86c2>] ? d_kill+0x35/0x3b [<c0438fa4>] ? dequeue_signal+0xa6/0x115 [<c0430d05>] do_group_exit+0x63/0x8a [<c0439504>] get_signal_to_deliver+0x2e1/0x2f9 [<c0401d9e>] do_notify_resume+0x7c/0x6b5 [<c043f601>] ? autoremove_wake_function+0x0/0x34 [<c04a864e>] ? __d_free+0x3d/0x40 [<c04a867b>] ? d_free+0x2a/0x3c [<c049ba7e>] ? vfs_write+0x103/0x117 [<c05fc8fa>] ? sys_socketcall+0x178/0x182 [<c0402a56>] work_notifysig+0x13/0x19 ---[ end trace 9db92c463e789fba ]--- Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/sctp/socket.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 35ba035970a2a..971890dbfea02 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) finish_wait(sk->sk_sleep, &wait); } -static void sctp_sock_rfree_frag(struct sk_buff *skb) -{ - struct sk_buff *frag; - - if (!skb->data_len) - goto done; - - /* Don't forget the fragments. */ - skb_walk_frags(skb, frag) - sctp_sock_rfree_frag(frag); - -done: - sctp_sock_rfree(skb); -} - static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) { struct sk_buff *frag; @@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsk->sk_receive_queue); __skb_queue_tail(&newsk->sk_receive_queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { event = sctp_skb2event(skb); if (event->asoc == assoc) { - sctp_sock_rfree_frag(skb); __skb_unlink(skb, &oldsp->pd_lobby); __skb_queue_tail(queue, skb); sctp_skb_set_owner_r_frag(skb, newsk); @@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, } - sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } - sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { - sctp_sock_rfree_frag(skb); + sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) sctp_skb_set_owner_r_frag(skb, newsk); - } /* Set the type of socket to indicate that it is peeled off from the * original UDP-style socket or created with the accept() call on a -- GitLab From 0ca1b08eba627b4245efd0f71b55a062bf163777 Mon Sep 17 00:00:00 2001 From: "David S. Miller" <davem@davemloft.net> Date: Mon, 6 Jul 2009 12:49:18 -0700 Subject: [PATCH 0770/1002] Revert "p54: Use SKB list handling helpers instead of by-hand code." This reverts commit a1091aae19b1d9c85d91c86915a611387f67a26b. --- drivers/net/wireless/p54/p54common.c | 46 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b618bd14583f9..48d81d98e12d4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -823,30 +823,30 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_info *range; unsigned long flags; - if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue))) + if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) return; - /* There used to be a check here to see if the SKB was on the - * TX queue or not. This can never happen because all SKBs we - * see here successfully went through p54_assign_address() - * which means the SKB is on the ->tx_queue. + /* + * don't try to free an already unlinked skb */ + if (unlikely((!skb->next) || (!skb->prev))) + return; spin_lock_irqsave(&priv->tx_queue.lock, flags); info = IEEE80211_SKB_CB(skb); range = (void *)info->rate_driver_data; - if (!skb_queue_is_first(&priv->tx_queue, skb)) { + if (skb->prev != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb)); + ni = IEEE80211_SKB_CB(skb->prev); mr = (struct p54_tx_info *)ni->rate_driver_data; } - if (!skb_queue_is_last(&priv->tx_queue, skb)) { + if (skb->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb)); + ni = IEEE80211_SKB_CB(skb->next); mr = (struct p54_tx_info *)ni->rate_driver_data; } __skb_unlink(skb, &priv->tx_queue); @@ -864,13 +864,15 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, unsigned long flags; spin_lock_irqsave(&priv->tx_queue.lock, flags); - skb_queue_walk(&priv->tx_queue, entry) { + entry = priv->tx_queue.next; + while (entry != (struct sk_buff *)&priv->tx_queue) { struct p54_hdr *hdr = (struct p54_hdr *) entry->data; if (hdr->req_id == req_id) { spin_unlock_irqrestore(&priv->tx_queue.lock, flags); return entry; } + entry = entry->next; } spin_unlock_irqrestore(&priv->tx_queue.lock, flags); return NULL; @@ -888,22 +890,24 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) int count, idx; spin_lock_irqsave(&priv->tx_queue.lock, flags); - skb_queue_walk(&priv->tx_queue, entry) { + entry = (struct sk_buff *) priv->tx_queue.next; + while (entry != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct p54_hdr *entry_hdr; struct p54_tx_data *entry_data; unsigned int pad = 0, frame_len; range = (void *)info->rate_driver_data; - if (range->start_addr != addr) + if (range->start_addr != addr) { + entry = entry->next; continue; + } - if (!skb_queue_is_last(&priv->tx_queue, entry)) { + if (entry->next != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *ni; struct p54_tx_info *mr; - ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, - entry)); + ni = IEEE80211_SKB_CB(entry->next); mr = (struct p54_tx_info *)ni->rate_driver_data; } @@ -1164,21 +1168,23 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, } } - skb_queue_walk(&priv->tx_queue, entry) { + entry = priv->tx_queue.next; + while (left--) { u32 hole_size; info = IEEE80211_SKB_CB(entry); range = (void *)info->rate_driver_data; hole_size = range->start_addr - last_addr; if (!target_skb && hole_size >= len) { - target_skb = skb_queue_prev(&priv->tx_queue, entry); + target_skb = entry->prev; hole_size -= len; target_addr = last_addr; } largest_hole = max(largest_hole, hole_size); last_addr = range->end_addr; + entry = entry->next; } if (!target_skb && priv->rx_end - last_addr >= len) { - target_skb = skb_peek_tail(&priv->tx_queue); + target_skb = priv->tx_queue.prev; largest_hole = max(largest_hole, priv->rx_end - last_addr - len); if (!skb_queue_empty(&priv->tx_queue)) { info = IEEE80211_SKB_CB(target_skb); @@ -2084,6 +2090,7 @@ static int p54_start(struct ieee80211_hw *dev) static void p54_stop(struct ieee80211_hw *dev) { struct p54_common *priv = dev->priv; + struct sk_buff *skb; mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; @@ -2098,7 +2105,8 @@ static void p54_stop(struct ieee80211_hw *dev) p54_tx_cancel(dev, priv->cached_beacon); priv->stop(dev); - skb_queue_purge(&priv->tx_queue); + while ((skb = skb_dequeue(&priv->tx_queue))) + kfree_skb(skb); priv->cached_beacon = NULL; priv->tsf_high32 = priv->tsf_low32 = 0; mutex_unlock(&priv->conf_mutex); -- GitLab From cbad1cbb51d92c0b5c3f47ef9dbf125de81fae08 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Mon, 6 Jul 2009 21:11:24 +0200 Subject: [PATCH 0771/1002] sisfb: fix regression with uninitalized fb_info->mm_lock mutex Remove redundant call to the sisfb_get_fix() before sis frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Tested-by: Wu Zhangjin <wuzhangjin@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/sis/sis_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index fd33455389b89..4a067f0d0ceb4 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -6367,7 +6367,6 @@ error_3: vfree(ivideo->bios_abase); sis_fb_info->fix = ivideo->sisfb_fix; sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; sis_fb_info->fbops = &sisfb_ops; - sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); sis_fb_info->pseudo_palette = ivideo->pseudo_palette; fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); -- GitLab From 9e2db5c90a25acf7657edb3687b8d5813ccddfee Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" <rpjday@crashcourse.ca> Date: Sun, 5 Jul 2009 12:08:00 -0700 Subject: [PATCH 0772/1002] vlynq: correct typo of missing "CONFIG_" prefix in ifdef Fix a typo in the vlynq bus driver which was missing the CONFIG_ prefix to turn on debugging code. Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca> Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/vlynq/vlynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vlynq/vlynq.c b/drivers/vlynq/vlynq.c index 7335433b067b3..f05d2a368367c 100644 --- a/drivers/vlynq/vlynq.c +++ b/drivers/vlynq/vlynq.c @@ -76,7 +76,7 @@ struct vlynq_regs { u32 int_device[8]; }; -#ifdef VLYNQ_DEBUG +#ifdef CONFIG_VLYNQ_DEBUG static void vlynq_dump_regs(struct vlynq_device *dev) { int i; -- GitLab From efc0cfa6d16103bd72a7c398f1321816b635370f Mon Sep 17 00:00:00 2001 From: Florian Fainelli <florian@openwrt.org> Date: Sun, 5 Jul 2009 12:08:02 -0700 Subject: [PATCH 0773/1002] vlynq: fix typo in Kconfig to enable debugging Fix a typo in the VLYNQ bus driver Kconfig which prevented to turn on VLYNQ bus debugging. Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/vlynq/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vlynq/Kconfig b/drivers/vlynq/Kconfig index f6542211db48f..a9efb16253215 100644 --- a/drivers/vlynq/Kconfig +++ b/drivers/vlynq/Kconfig @@ -13,7 +13,7 @@ config VLYNQ config VLYNQ_DEBUG bool "VLYNQ bus debug" - depends on VLYNQ && KERNEL_DEBUG + depends on VLYNQ && DEBUG_KERNEL help Turn on VLYNQ bus debugging. -- GitLab From 28df30e61b46a33d1f0bb60757747396886ef687 Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Sun, 5 Jul 2009 12:08:03 -0700 Subject: [PATCH 0774/1002] rtc: ds1374, fix lock imbalance When i2c_smbus_read_byte_data fails in ds1374_work, we forgot to unlock the held lock. Fix that. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Scott Wood <scottwood@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/rtc/rtc-ds1374.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 32b27739ec2a4..713f7bf5afb33 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -283,7 +283,7 @@ static void ds1374_work(struct work_struct *work) stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR); if (stat < 0) - return; + goto unlock; if (stat & DS1374_REG_SR_AF) { stat &= ~DS1374_REG_SR_AF; @@ -302,7 +302,7 @@ static void ds1374_work(struct work_struct *work) out: if (!ds1374->exiting) enable_irq(client->irq); - +unlock: mutex_unlock(&ds1374->mutex); } -- GitLab From f386c61fe1a1f36f0e434f1b577e6b112698caf7 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Date: Sun, 5 Jul 2009 12:08:06 -0700 Subject: [PATCH 0775/1002] gcov: exclude code operating in userspace from profiling Fix for this issue on x86_64: rostedt@goodmis.org wrote: > On bootup of the latest kernel my init segfaults. Debugging it, > I found that vread_tsc (a vsyscall) increments some strange > kernel memory: > > 0000000000000000 <vread_tsc>: > 0: 55 push %rbp > 1: 48 ff 05 00 00 00 00 incq 0(%rip) > # 8 <vread_tsc+0x8> > 4: R_X86_64_PC32 .bss+0x3c > 8: 48 89 e5 mov %rsp,%rbp > b: 66 66 90 xchg %ax,%ax > e: 48 ff 05 00 00 00 00 incq 0(%rip) > # 15 <vread_tsc+0x15> > 11: R_X86_64_PC32 .bss+0x44 > 15: 66 66 90 xchg %ax,%ax > 18: 48 ff 05 00 00 00 00 incq 0(%rip) > # 1f <vread_tsc+0x1f> > 1b: R_X86_64_PC32 .bss+0x4c > 1f: 0f 31 rdtsc > > > Those "incq" is very bad to happen in vsyscall memory, since > userspace can not modify it. You need to make something prevent > profiling of vsyscall memory (like I do with ftrace). Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Reported-by: Steven Rostedt <rostedt@goodmis.org> Tested-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/kernel/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 6c327b852e23b..430d5b24af7b2 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -26,6 +26,8 @@ CFLAGS_tsc.o := $(nostackp) CFLAGS_paravirt.o := $(nostackp) GCOV_PROFILE_vsyscall_64.o := n GCOV_PROFILE_hpet.o := n +GCOV_PROFILE_tsc.o := n +GCOV_PROFILE_paravirt.o := n obj-y := process_$(BITS).o signal.o entry_$(BITS).o obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o -- GitLab From 3beab0b42413e83a7907db7176b54c840fc75a81 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" <yanmin_zhang@linux.intel.com> Date: Sun, 5 Jul 2009 12:08:08 -0700 Subject: [PATCH 0776/1002] sys_sync(): fix 16% performance regression in ffsb create_4k test I run many ffsb test cases on JBODs (typically 13/12 disks). Comparing with kernel 2.6.30, 2.6.31-rc1 has about 16% regression with ffsb_create_4k. The sub test case creates files continuously for 10 minitues and every file is 1MB. Bisect located below patch. 5cee5815d1564bbbd505fea86f4550f1efdb5cd0 is first bad commit commit 5cee5815d1564bbbd505fea86f4550f1efdb5cd0 Author: Jan Kara <jack@suse.cz> Date: Mon Apr 27 16:43:51 2009 +0200 vfs: Make sys_sync() use fsync_super() (version 4) It is unnecessarily fragile to have two places (fsync_super() and do_sync()) doing data integrity sync of the filesystem. Alter __fsync_super() to accommodate needs of both callers and use it. So after this patch __fsync_super() is the only place where we gather all the calls needed to properly send all data on a filesystem to disk. As a matter of fact, ffsb calls sys_sync in the end to make sure all data is flushed to disks and the flushing is counted into the result. vmstat shows ffsb is blocked when syncing for a long time. With 2.6.30, ffsb is blocked for a short time. I checked the patch and did experiments to recover the original methods. Eventually, the root cause is the patch deletes the calling to wakeup_pdflush when syncing, so only ffsb is blocked on disk I/O. wakeup_pdflush could ask pdflush to write back pages with ffsb at the same time. [akpm@linux-foundation.org: restore comment too] Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com> Cc: Jan Kara <jack@suse.cz> Cc: Al Viro <viro@zeniv.linux.org.uk> Acked-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/sync.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/sync.c b/fs/sync.c index dd200025af852..3422ba61d86dc 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -112,8 +112,13 @@ static void sync_filesystems(int wait) mutex_unlock(&mutex); } +/* + * sync everything. Start out by waking pdflush, because that writes back + * all queues in parallel. + */ SYSCALL_DEFINE0(sync) { + wakeup_pdflush(0); sync_filesystems(0); sync_filesystems(1); if (unlikely(laptop_mode)) -- GitLab From a65e7bfcd74e4c0939f235d2bf9f48ddb3a57991 Mon Sep 17 00:00:00 2001 From: Hui Zhu <teawater@gmail.com> Date: Sun, 5 Jul 2009 12:08:15 -0700 Subject: [PATCH 0777/1002] elf: fix multithreaded program core dumping on arm Fix the multithread program core thread message error. This issue affects arches with neither has CORE_DUMP_USE_REGSET nor ELF_CORE_COPY_TASK_REGS, ARM is one of them. The thread message of core file is generated in elf_dump_thread_status. The register values is set by elf_core_copy_task_regs in this function. If an arch doesn't define ELF_CORE_COPY_TASK_REGS, elf_core_copy_task_regs() will do nothing. Then the core file will not have the register message of thread. So add elf_core_copy_regs to set regiser values if ELF_CORE_COPY_TASK_REGS doesn't define. The following is how to reproduce this issue: cat 1.c #include <stdio.h> #include <pthread.h> #include <assert.h> void td1(void * i) { while (1) { printf ("1\n"); sleep (1); } return; } void td2(void * i) { while (1) { printf ("2\n"); sleep (1); } return; } int main(int argc,char *argv[],char *envp[]) { pthread_t t1,t2; pthread_create(&t1, NULL, (void*)td1, NULL); pthread_create(&t2, NULL, (void*)td2, NULL); sleep (10); assert(0); return (0); } arm-xxx-gcc -g -lpthread 1.c -o 1 copy 1.c and 1 to a arm board. Goto this board. ulimit -c 1800000 ./1 # ./1 1 2 1 ... ... 1 1: 1.c:37: main: Assertion `0' failed. Aborted (core dumped) Then you can get a core file. gdb 1 core.xxx Without the patch: (gdb) info threads 3 process 909 0x00000000 in ?? () 2 process 908 0x00000000 in ?? () * 1 process 907 0x4a6e2238 in raise () from /lib/libc.so.6 You can found that the pc of 909 and 908 is 0x00000000. With the patch: (gdb) info threads 3 process 885 0x4a749974 in nanosleep () from /lib/libc.so.6 2 process 884 0x4a749974 in nanosleep () from /lib/libc.so.6 * 1 process 883 0x4a6e2238 in raise () from /lib/libc.so.6 The pc of 885 and 884 is right. Signed-off-by: Hui Zhu <teawater@gmail.com> Cc: Amerigo Wang <xiyou.wangcong@gmail.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: David Howells <dhowells@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Jakub Jelinek <jakub@redhat.com> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/elfcore.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 7605c5e9589f4..03ec167798022 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -125,6 +125,8 @@ static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* #ifdef ELF_CORE_COPY_TASK_REGS return ELF_CORE_COPY_TASK_REGS(t, elfregs); +#else + elf_core_copy_regs(elfregs, task_pt_regs(t)); #endif return 0; } -- GitLab From c8236db9cd7aa492dcfcdcca702638e704abed49 Mon Sep 17 00:00:00 2001 From: Josef Bacik <josef@redhat.com> Date: Sun, 5 Jul 2009 12:08:18 -0700 Subject: [PATCH 0778/1002] mm: mark page accessed before we write_end() In testing a backport of the write_begin/write_end AOPs, a 10% re-read regression was noticed when running iozone. This regression was introduced because the old AOPs would always do a mark_page_accessed(page) after the commit_write, but when the new AOPs where introduced, the only place this was kept was in pagecache_write_end(). This patch does the same thing in the generic case as what is done in pagecache_write_end(), which is just to mark the page accessed before we do write_end(). Signed-off-by: Josef Bacik <jbacik@redhat.com> Acked-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- mm/filemap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/filemap.c b/mm/filemap.c index 22396713feb96..ccea3b665c125 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2272,6 +2272,7 @@ static ssize_t generic_perform_write(struct file *file, pagefault_enable(); flush_dcache_page(page); + mark_page_accessed(page); status = a_ops->write_end(file, mapping, pos, bytes, copied, page, fsdata); if (unlikely(status < 0)) -- GitLab From 5bfd7560979062ad75c9805c1719cec990b5db29 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee <cernekee@gmail.com> Date: Sun, 5 Jul 2009 12:08:19 -0700 Subject: [PATCH 0779/1002] Fix virt_to_phys() warnings These warnings were observed on MIPS32 using 2.6.31-rc1 and gcc-4.2.0: mm/page_alloc.c: In function 'alloc_pages_exact': mm/page_alloc.c:1986: warning: passing argument 1 of 'virt_to_phys' makes pointer from integer without a cast drivers/usb/mon/mon_bin.c: In function 'mon_alloc_buff': drivers/usb/mon/mon_bin.c:1264: warning: passing argument 1 of 'virt_to_phys' makes pointer from integer without a cast [akpm@linux-foundation.org: fix kernel/perf_counter.c too] Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/mon/mon_bin.c | 2 +- kernel/perf_counter.c | 2 +- mm/page_alloc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index f8d9045d668a1..0f7a30b7d2d16 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages) return -ENOMEM; } map[n].ptr = (unsigned char *) vaddr; - map[n].pg = virt_to_page(vaddr); + map[n].pg = virt_to_page((void *) vaddr); } return 0; } diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index d55a50da2347f..a641eb753b8cc 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -2020,7 +2020,7 @@ static int perf_mmap_data_alloc(struct perf_counter *counter, int nr_pages) static void perf_mmap_free_page(unsigned long addr) { - struct page *page = virt_to_page(addr); + struct page *page = virt_to_page((void *)addr); page->mapping = NULL; __free_page(page); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e0f2cdf9d8b1f..ad7cd1c56b07c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1983,7 +1983,7 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask) unsigned long alloc_end = addr + (PAGE_SIZE << order); unsigned long used = addr + PAGE_ALIGN(size); - split_page(virt_to_page(addr), order); + split_page(virt_to_page((void *)addr), order); while (used < alloc_end) { free_page(used); used += PAGE_SIZE; -- GitLab From 600ce1a0faafeed1ce6bcfd421bc040b941cbbc1 Mon Sep 17 00:00:00 2001 From: InKi Dae <daeinki@gmail.com> Date: Sun, 5 Jul 2009 12:08:21 -0700 Subject: [PATCH 0780/1002] drivers/video/s3c-fb.c: fix clock setting for Samsung SoC Framebuffer Correct the CLKVAL_F field value of VIDEO MAIN CONTROLLER 0 REGITSTER. Frame Rate is 1 / [ { (VSPW+1) + (VBPD+1) + (LIINEVAL + 1) + (VFPD+1) } x {(HSPW+1) + (HBPD +1) + (HFPD+1) + (HOZVAL + 1) } x { ( CLKVAL+1 ) / ( Frequency of Clock source ) } ] and VCLK = Video Clock Source / (CLKVAL +1). therefore CLKVAL_F should be "CLKVAL_F = Frequency of Clock source / pixel clock * refresh". for this, I added refresh value in platform data like below. static struct s3c_fb_pd_win xxx_fb_win0 = { /* this is to ensure we use win0 */ .win_mode = { .refresh = 60, .pixclock = (66+4+2+480)*(15+5+3+800), .left_margin = 66, .right_margin = 2, .upper_margin = 15, .lower_margin = 3, .hsync_len = 4, .vsync_len = 5, .xres = 480, .yres = 800, }, .max_bpp = 32, .default_bpp = 24, }; static struct s3c_fb_platdata xxx_lcd_pdata __initdata = { .win[0] = &xxx_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, .setup_gpio = s5pc1xx_fb_gpio_setup_24bpp, }; xxx_machine_init() { . . . s3c_fb_set_platdata(&xxx_lcd_pdata); } platform data defined in machine code should be setting using s3c_fb_set_platdata(). Signed-off-by: InKi Dae <inki.dae@samsung.com> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/s3c-fb.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 43680e545427f..bb63c07e13de5 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /** * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. + * @id: window id. * @sfb: The hardware state. * @pixclock: The pixel clock wanted, in picoseconds. * * Given the specified pixel clock, work out the necessary divider to get * close to the output frequency. */ -static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) +static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) { + struct s3c_fb_pd_win *win = sfb->pdata->win[id]; unsigned long clk = clk_get_rate(sfb->bus_clk); - unsigned long long tmp; unsigned int result; - tmp = (unsigned long long)clk; - tmp *= pixclk; - - do_div(tmp, 1000000000UL); - result = (unsigned int)tmp / 1000; + pixclk *= win->win_mode.refresh; + result = clk / pixclk; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", pixclk, clk, result, clk / result); @@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info) struct s3c_fb *sfb = win->parent; void __iomem *regs = sfb->regs; int win_no = win->index; + u32 osdc_data = 0; u32 data; u32 pagewidth; int clkdiv; @@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* use window 0 as the basis for the lcd output timings */ if (win_no == 0) { - clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); + clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); data = sfb->pdata->vidcon0; data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); @@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info) data = var->xres * var->yres; - u32 osdc_data = 0; - osdc_data = VIDISD14C_ALPHA1_R(0xf) | VIDISD14C_ALPHA1_G(0xf) | VIDISD14C_ALPHA1_B(0xf); -- GitLab From 82e3310ace59794ecf0f531eca94647b2863dfda Mon Sep 17 00:00:00 2001 From: Tobias Doerffel <tobias.doerffel@gmail.com> Date: Sun, 5 Jul 2009 12:08:23 -0700 Subject: [PATCH 0781/1002] linux/sysrq.h needs linux/errno.h In include/linux/sysrq.h the constant EINVAL is being used but is undefined if include/linux/errno.h is not included before. Fix this by adding #include <linux/errno.h> at the beginning. Signed-off-by: Tobias Doerffel <tobias.doerffel@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/sysrq.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h index 98a1d8cfb73d1..99adcdc0d3ca9 100644 --- a/include/linux/sysrq.h +++ b/include/linux/sysrq.h @@ -14,6 +14,8 @@ #ifndef _LINUX_SYSRQ_H #define _LINUX_SYSRQ_H +#include <linux/errno.h> + struct pt_regs; struct tty_struct; -- GitLab From 793285fcafce4719a05e0c99fa74b188157fe7fe Mon Sep 17 00:00:00 2001 From: Oleg Nesterov <oleg@redhat.com> Date: Sun, 5 Jul 2009 12:08:26 -0700 Subject: [PATCH 0782/1002] cred_guard_mutex: do not return -EINTR to user-space do_execve() and ptrace_attach() return -EINTR if mutex_lock_interruptible(->cred_guard_mutex) fails. This is not right, change the code to return ERESTARTNOINTR. Perhaps we should also change proc_pid_attr_write(). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: David Howells <dhowells@redhat.com> Acked-by: Roland McGrath <roland@redhat.com> Cc: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/compat.c | 4 ++-- fs/exec.c | 4 ++-- kernel/ptrace.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index cdd51a3a7c537..fbadb947727b1 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1486,8 +1486,8 @@ int compat_do_execve(char * filename, if (!bprm) goto out_files; - retval = mutex_lock_interruptible(¤t->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; current->in_execve = 1; diff --git a/fs/exec.c b/fs/exec.c index e639957d7a57a..4a8849e45b219 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1277,8 +1277,8 @@ int do_execve(char * filename, if (!bprm) goto out_files; - retval = mutex_lock_interruptible(¤t->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; current->in_execve = 1; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 61c78b2c07bae..082c320e4dbf0 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -181,8 +181,8 @@ int ptrace_attach(struct task_struct *task) * interference; SUID, SGID and LSM creds get determined differently * under ptrace. */ - retval = mutex_lock_interruptible(&task->cred_guard_mutex); - if (retval < 0) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) goto out; task_lock(task); -- GitLab From 4148df9b0f38bdd362dd91d52076926c11cbe5a9 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Mon, 6 Jul 2009 00:25:57 +0900 Subject: [PATCH 0783/1002] fb: Initialize fb_info mutexes in framebuffer_alloc() This way they'll be properly initialized early enough for users that may touch them before the framebuffer has been registered. Drivers that allocate their fb_info structure some other way (like matrocfb's broken static allocation) need to be fixed up appropriately. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/fbmem.c | 2 -- drivers/video/fbsysfs.c | 3 +++ drivers/video/matrox/matroxfb_base.c | 1 + drivers/video/sm501fb.c | 2 -- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 53ea05645ff8e..53eb39652791d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1513,8 +1513,6 @@ register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; - mutex_init(&fb_info->lock); - mutex_init(&fb_info->mm_lock); fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index d4a2c11d98097..afc04df39a038 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -62,6 +62,9 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) mutex_init(&info->bl_curve_mutex); #endif + mutex_init(&info->lock); + mutex_init(&info->mm_lock); + return info; #undef PADDING #undef BYTES_PER_LONG diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 59c3a2e149137..76bc51b616d1c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -2083,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm spin_lock_init(&ACCESS_FBINFO(lock.accel)); init_rwsem(&ACCESS_FBINFO(crtc2.lock)); init_rwsem(&ACCESS_FBINFO(altout.lock)); + mutex_init(&ACCESS_FBINFO(fbcon).lock); mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); ACCESS_FBINFO(irq_flags) = 0; init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 16d4f4c7d52b5..98f24f0ec00df 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1624,8 +1624,6 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info, if (!fbi) return 0; - mutex_init(&info->fb[head]->mm_lock); - ret = sm501fb_init_fb(info->fb[head], head, drvname); if (ret) { dev_err(info->dev, "cannot initialise fb %s\n", drvname); -- GitLab From 7d26e2d5e2da37e92c6c7644b26b294dedd8c982 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" <venkatesh.pallipadi@intel.com> Date: Thu, 2 Jul 2009 17:08:30 -0700 Subject: [PATCH 0784/1002] [CPUFREQ] Eliminate the recent lockdep warnings in cpufreq Commit b14893a62c73af0eca414cfed505b8c09efc613c although it was very much needed to properly cleanup ondemand timer, opened-up a can of worms related to locking dependencies in cpufreq. Patch here defines the need for dbs_mutex and cleans up its usage in ondemand governor. This also resolves the lockdep warnings reported here http://lkml.indiana.edu/hypermail/linux/kernel/0906.1/01925.html http://lkml.indiana.edu/hypermail/linux/kernel/0907.0/00820.html and few others.. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Dave Jones <davej@redhat.com> --- drivers/cpufreq/cpufreq.c | 4 ++-- drivers/cpufreq/cpufreq_conservative.c | 27 +++++++++++--------------- drivers/cpufreq/cpufreq_ondemand.c | 27 +++++++++++--------------- 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6e2ec0b189489..c7fe16e0474b7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1070,8 +1070,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) spin_unlock_irqrestore(&cpufreq_driver_lock, flags); #endif - unlock_policy_rwsem_write(cpu); - if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); @@ -1088,6 +1086,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev) if (cpufreq_driver->exit) cpufreq_driver->exit(data); + unlock_policy_rwsem_write(cpu); + free_cpumask_var(data->related_cpus); free_cpumask_var(data->cpus); kfree(data); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 7fc58af748b49..58889f26029a6 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -70,15 +70,10 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ /* - * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug - * lock and dbs_mutex. cpu_hotplug lock should always be held before - * dbs_mutex. If any function that can potentially take cpu_hotplug lock - * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then - * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock - * is recursive for the same process. -Venki - * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it - * would deadlock with cancel_delayed_work_sync(), which is needed for proper - * raceless workqueue teardown. + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on + * different CPUs. It protects dbs_enable in governor start/stop. It also + * serializes governor limit_change with do_dbs_timer. We do not want + * do_dbs_timer to run when user is changing the governor or limits. */ static DEFINE_MUTEX(dbs_mutex); @@ -488,18 +483,17 @@ static void do_dbs_timer(struct work_struct *work) delay -= jiffies % delay; - if (lock_policy_rwsem_write(cpu) < 0) - return; + mutex_lock(&dbs_mutex); if (!dbs_info->enable) { - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_mutex); return; } dbs_check_cpu(dbs_info); queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -590,15 +584,16 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, &dbs_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); } - dbs_timer_init(this_dbs_info); - mutex_unlock(&dbs_mutex); + dbs_timer_init(this_dbs_info); + break; case CPUFREQ_GOV_STOP: - mutex_lock(&dbs_mutex); dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); dbs_enable--; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 1911d1729353f..246ae147df74f 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -78,15 +78,10 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ /* - * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug - * lock and dbs_mutex. cpu_hotplug lock should always be held before - * dbs_mutex. If any function that can potentially take cpu_hotplug lock - * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then - * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock - * is recursive for the same process. -Venki - * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it - * would deadlock with cancel_delayed_work_sync(), which is needed for proper - * raceless workqueue teardown. + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on + * different CPUs. It protects dbs_enable in governor start/stop. It also + * serializes governor limit_change with do_dbs_timer. We do not want + * do_dbs_timer to run when user is changing the governor or limits. */ static DEFINE_MUTEX(dbs_mutex); @@ -494,11 +489,10 @@ static void do_dbs_timer(struct work_struct *work) delay -= jiffies % delay; - if (lock_policy_rwsem_write(cpu) < 0) - return; + mutex_lock(&dbs_mutex); if (!dbs_info->enable) { - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_mutex); return; } @@ -517,7 +511,7 @@ static void do_dbs_timer(struct work_struct *work) dbs_info->freq_lo, CPUFREQ_RELATION_H); } queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); - unlock_policy_rwsem_write(cpu); + mutex_unlock(&dbs_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -598,14 +592,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, max(min_sampling_rate, latency * LATENCY_MULTIPLIER); } - dbs_timer_init(this_dbs_info); - mutex_unlock(&dbs_mutex); + + dbs_timer_init(this_dbs_info); break; case CPUFREQ_GOV_STOP: - mutex_lock(&dbs_mutex); dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); dbs_enable--; mutex_unlock(&dbs_mutex); -- GitLab From 37c90e8887efd218dc4af949b7f498ca2da4af9f Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" <venkatesh.pallipadi@intel.com> Date: Thu, 2 Jul 2009 17:08:31 -0700 Subject: [PATCH 0785/1002] [CPUFREQ] Mark policy_rwsem as going static in cpufreq.c wont be exported lock_policy_rwsem_* and unlock_policy_rwsem_* routines in cpufreq.c are currently exported to drivers. Improper use of those locks can result in deadlocks and it is better to keep the locks localized. Two previous in-kernel users of these interfaces (ondemand and conservative), do not use this interfaces any more. Schedule them for removal. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Dave Jones <davej@redhat.com> --- Documentation/feature-removal-schedule.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index f8cd450be9aa8..09e031c558875 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -458,3 +458,13 @@ Why: Remove the old legacy 32bit machine check code. This has been but the old version has been kept around for easier testing. Note this doesn't impact the old P5 and WinChip machine check handlers. Who: Andi Kleen <andi@firstfloor.org> + +---------------------------- + +What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be + exported interface anymore. +When: 2.6.33 +Why: cpu_policy_rwsem has a new cleaner definition making it local to + cpufreq core and contained inside cpufreq.c. Other dependent + drivers should not use it in order to safely avoid lockdep issues. +Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> -- GitLab From 5a75c82828e7c088ca6e7b4827911dc29cc8e774 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" <venkatesh.pallipadi@intel.com> Date: Thu, 2 Jul 2009 17:08:32 -0700 Subject: [PATCH 0786/1002] [CPUFREQ] Cleanup locking in ondemand governor Redesign the locking inside ondemand driver. Make dbs_mutex handle all the global state changes inside the driver and invent a new percpu mutex to serialize percpu timer and frequency limit change. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Dave Jones <davej@redhat.com> --- drivers/cpufreq/cpufreq_ondemand.c | 62 +++++++++++++----------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 246ae147df74f..d6ba14276bb1b 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -70,8 +70,13 @@ struct cpu_dbs_info_s { unsigned int freq_lo_jiffies; unsigned int freq_hi_jiffies; int cpu; - unsigned int enable:1, - sample_type:1; + unsigned int sample_type:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -79,9 +84,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ /* * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on - * different CPUs. It protects dbs_enable in governor start/stop. It also - * serializes governor limit_change with do_dbs_timer. We do not want - * do_dbs_timer to run when user is changing the governor or limits. + * different CPUs. It protects dbs_enable in governor start/stop. */ static DEFINE_MUTEX(dbs_mutex); @@ -187,13 +190,18 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy, return freq_hi; } +static void ondemand_powersave_bias_init_cpu(int cpu) +{ + struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + static void ondemand_powersave_bias_init(void) { int i; for_each_online_cpu(i) { - struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i); - dbs_info->freq_table = cpufreq_frequency_get_table(i); - dbs_info->freq_lo = 0; + ondemand_powersave_bias_init_cpu(i); } } @@ -235,12 +243,10 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; mutex_lock(&dbs_mutex); - if (ret != 1) { - mutex_unlock(&dbs_mutex); - return -EINVAL; - } dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); mutex_unlock(&dbs_mutex); @@ -254,13 +260,12 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, int ret; ret = sscanf(buf, "%u", &input); - mutex_lock(&dbs_mutex); if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || input < MIN_FREQUENCY_UP_THRESHOLD) { - mutex_unlock(&dbs_mutex); return -EINVAL; } + mutex_lock(&dbs_mutex); dbs_tuners_ins.up_threshold = input; mutex_unlock(&dbs_mutex); @@ -358,9 +363,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) struct cpufreq_policy *policy; unsigned int j; - if (!this_dbs_info->enable) - return; - this_dbs_info->freq_lo = 0; policy = this_dbs_info->cur_policy; @@ -488,13 +490,7 @@ static void do_dbs_timer(struct work_struct *work) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - - mutex_lock(&dbs_mutex); - - if (!dbs_info->enable) { - mutex_unlock(&dbs_mutex); - return; - } + mutex_lock(&dbs_info->timer_mutex); /* Common NORMAL_SAMPLE setup */ dbs_info->sample_type = DBS_NORMAL_SAMPLE; @@ -511,7 +507,7 @@ static void do_dbs_timer(struct work_struct *work) dbs_info->freq_lo, CPUFREQ_RELATION_H); } queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); - mutex_unlock(&dbs_mutex); + mutex_unlock(&dbs_info->timer_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -520,8 +516,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - dbs_info->enable = 1; - ondemand_powersave_bias_init(); dbs_info->sample_type = DBS_NORMAL_SAMPLE; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work, @@ -530,7 +524,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { - dbs_info->enable = 0; cancel_delayed_work_sync(&dbs_info->work); } @@ -549,19 +542,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; - if (this_dbs_info->enable) /* Already enabled */ - break; - mutex_lock(&dbs_mutex); - dbs_enable++; rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); if (rc) { - dbs_enable--; mutex_unlock(&dbs_mutex); return rc; } + dbs_enable++; for_each_cpu(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); @@ -575,6 +564,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, } } this_dbs_info->cpu = cpu; + ondemand_powersave_bias_init_cpu(cpu); + mutex_init(&this_dbs_info->timer_mutex); /* * Start the timerschedule work, when this governor * is used for first time @@ -602,20 +593,21 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); + mutex_destroy(&this_dbs_info->timer_mutex); dbs_enable--; mutex_unlock(&dbs_mutex); break; case CPUFREQ_GOV_LIMITS: - mutex_lock(&dbs_mutex); + mutex_lock(&this_dbs_info->timer_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); - mutex_unlock(&dbs_mutex); + mutex_unlock(&this_dbs_info->timer_mutex); break; } return 0; -- GitLab From ee88415caf736b89500f16e0a545614541a45005 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" <venkatesh.pallipadi@intel.com> Date: Thu, 2 Jul 2009 17:08:33 -0700 Subject: [PATCH 0787/1002] [CPUFREQ] Cleanup locking in conservative governor Redesign the locking inside conservative driver. Make dbs_mutex handle all the global state changes inside the driver and invent a new percpu mutex to serialize percpu timer and frequency limit change. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Dave Jones <davej@redhat.com> --- drivers/cpufreq/cpufreq_conservative.c | 34 ++++++++++---------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 58889f26029a6..57490502b21cb 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -63,7 +63,12 @@ struct cpu_dbs_info_s { unsigned int down_skip; unsigned int requested_freq; int cpu; - unsigned int enable:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -71,9 +76,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ /* * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on - * different CPUs. It protects dbs_enable in governor start/stop. It also - * serializes governor limit_change with do_dbs_timer. We do not want - * do_dbs_timer to run when user is changing the governor or limits. + * different CPUs. It protects dbs_enable in governor start/stop. */ static DEFINE_MUTEX(dbs_mutex); @@ -138,9 +141,6 @@ dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, struct cpufreq_policy *policy; - if (!this_dbs_info->enable) - return 0; - policy = this_dbs_info->cur_policy; /* @@ -483,17 +483,12 @@ static void do_dbs_timer(struct work_struct *work) delay -= jiffies % delay; - mutex_lock(&dbs_mutex); - - if (!dbs_info->enable) { - mutex_unlock(&dbs_mutex); - return; - } + mutex_lock(&dbs_info->timer_mutex); dbs_check_cpu(dbs_info); queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); - mutex_unlock(&dbs_mutex); + mutex_unlock(&dbs_info->timer_mutex); } static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) @@ -502,7 +497,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); delay -= jiffies % delay; - dbs_info->enable = 1; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work, delay); @@ -510,7 +504,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { - dbs_info->enable = 0; cancel_delayed_work_sync(&dbs_info->work); } @@ -529,9 +522,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; - if (this_dbs_info->enable) /* Already enabled */ - break; - mutex_lock(&dbs_mutex); rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); @@ -555,6 +545,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->down_skip = 0; this_dbs_info->requested_freq = policy->cur; + mutex_init(&this_dbs_info->timer_mutex); dbs_enable++; /* * Start the timerschedule work, when this governor @@ -596,6 +587,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); sysfs_remove_group(&policy->kobj, &dbs_attr_group); dbs_enable--; + mutex_destroy(&this_dbs_info->timer_mutex); /* * Stop the timerschedule work, when this governor @@ -611,7 +603,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: - mutex_lock(&dbs_mutex); + mutex_lock(&this_dbs_info->timer_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, @@ -620,7 +612,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, __cpufreq_driver_target( this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); - mutex_unlock(&dbs_mutex); + mutex_unlock(&this_dbs_info->timer_mutex); break; } -- GitLab From 3f4a782b5ce2698b1870b5a7b573cd721d4fce33 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Date: Fri, 3 Jul 2009 11:25:16 -0400 Subject: [PATCH 0788/1002] [CPUFREQ] fix (utter) cpufreq_add_dev mess OK, I've tried to clean it up the best I could, but please test this with concurrent cpu hotplug and cpufreq add/remove in loops. I'm sure we will make other interesting findings. This is step one of fixing the overall locking dependency mess in cpufreq. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> CC: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> CC: rjw@sisk.pl CC: mingo@elte.hu CC: Shaohua Li <shaohua.li@intel.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Dave Young <hidave.darkstar@gmail.com> CC: "Rafael J. Wysocki" <rjw@sisk.pl> CC: Rusty Russell <rusty@rustcorp.com.au> CC: sven.wegener@stealer.net CC: cpufreq@vger.kernel.org CC: Thomas Renninger <trenn@suse.de> Signed-off-by: Dave Jones <davej@redhat.com> --- drivers/cpufreq/cpufreq.c | 65 ++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c7fe16e0474b7..c668ac855f71c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = { * cpufreq_add_dev - add a CPU device * * Adds the cpufreq interface for a CPU device. + * + * The Oracle says: try running cpufreq registration/unregistration concurrently + * with with cpu hotplugging and all hell will break loose. Tried to clean this + * mess up, but more thorough testing is needed. - Mathieu */ static int cpufreq_add_dev(struct sys_device *sys_dev) { @@ -804,15 +808,12 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) goto nomem_out; } if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) { - kfree(policy); ret = -ENOMEM; - goto nomem_out; + goto err_free_policy; } if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { - free_cpumask_var(policy->cpus); - kfree(policy); ret = -ENOMEM; - goto nomem_out; + goto err_free_cpumask; } policy->cpu = cpu; @@ -820,7 +821,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) /* Initially set CPU itself as the policy_cpu */ per_cpu(policy_cpu, cpu) = cpu; - lock_policy_rwsem_write(cpu); + ret = (lock_policy_rwsem_write(cpu) < 0); + WARN_ON(ret); init_completion(&policy->kobj_unregister); INIT_WORK(&policy->update, handle_update); @@ -833,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = cpufreq_driver->init(policy); if (ret) { dprintk("initialization failed\n"); - goto err_out; + goto err_unlock_policy; } policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; @@ -858,15 +860,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) /* Check for existing affected CPUs. * They may not be aware of it due to CPU Hotplug. */ - managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */ + managed_policy = cpufreq_cpu_get(j); if (unlikely(managed_policy)) { /* Set proper policy_cpu */ unlock_policy_rwsem_write(cpu); per_cpu(policy_cpu, cpu) = managed_policy->cpu; - if (lock_policy_rwsem_write(cpu) < 0) - goto err_out_driver_exit; + if (lock_policy_rwsem_write(cpu) < 0) { + /* Should not go through policy unlock path */ + if (cpufreq_driver->exit) + cpufreq_driver->exit(policy); + ret = -EBUSY; + cpufreq_cpu_put(managed_policy); + goto err_free_cpumask; + } spin_lock_irqsave(&cpufreq_driver_lock, flags); cpumask_copy(managed_policy->cpus, policy->cpus); @@ -877,12 +885,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = sysfs_create_link(&sys_dev->kobj, &managed_policy->kobj, "cpufreq"); - if (ret) - goto err_out_driver_exit; - - cpufreq_debug_enable_ratelimit(); - ret = 0; - goto err_out_driver_exit; /* call driver->exit() */ + if (!ret) + cpufreq_cpu_put(managed_policy); + /* + * Success. We only needed to be added to the mask. + * Call driver->exit() because only the cpu parent of + * the kobj needed to call init(). + */ + goto out_driver_exit; /* call driver->exit() */ } } #endif @@ -892,25 +902,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, "cpufreq"); if (ret) - goto err_out_driver_exit; + goto out_driver_exit; /* set up files for this cpu device */ drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; drv_attr++; } if (cpufreq_driver->get) { ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; } if (cpufreq_driver->target) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) - goto err_out_driver_exit; + goto err_out_kobj_put; } spin_lock_irqsave(&cpufreq_driver_lock, flags); @@ -928,12 +938,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) continue; dprintk("CPU %u already managed, adding link\n", j); - cpufreq_cpu_get(cpu); + managed_policy = cpufreq_cpu_get(cpu); cpu_sys_dev = get_cpu_sysdev(j); ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, "cpufreq"); - if (ret) + if (ret) { + cpufreq_cpu_put(managed_policy); goto err_out_unregister; + } } policy->governor = NULL; /* to assure that the starting sequence is @@ -965,17 +977,20 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) per_cpu(cpufreq_cpu_data, j) = NULL; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +err_out_kobj_put: kobject_put(&policy->kobj); wait_for_completion(&policy->kobj_unregister); -err_out_driver_exit: +out_driver_exit: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); -err_out: +err_unlock_policy: unlock_policy_rwsem_write(cpu); +err_free_cpumask: + free_cpumask_var(policy->cpus); +err_free_policy: kfree(policy); - nomem_out: module_put(cpufreq_driver->owner); module_out: -- GitLab From a2e1b4c31257c07f148a89eb7eea7ca959fd0642 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf <mark.langsdorf@amd.com> Date: Sun, 26 Jul 2009 10:55:25 -0500 Subject: [PATCH 0789/1002] [CPUFREQ] Powernow-k8: support family 0xf with 2 low p-states Provide support for family 0xf processors with 2 P-states below the elevator voltage. Remove the checks that prevent this configuration from being supported and increase the transition voltage to prevent errors during the transition. Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com> Signed-off-by: Dave Jones <davej@redhat.com> --- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 30 +++++++++-------------- arch/x86/kernel/cpu/cpufreq/powernow-k8.h | 3 ++- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 81cbe64ed6b49..ae068f59603f4 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -299,7 +299,7 @@ static int transition_pstate(struct powernow_k8_data *data, u32 pstate) static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid) { - if (core_voltage_pre_transition(data, reqvid)) + if (core_voltage_pre_transition(data, reqvid, reqfid)) return 1; if (core_frequency_transition(data, reqfid)) @@ -327,17 +327,20 @@ static int transition_fid_vid(struct powernow_k8_data *data, /* Phase 1 - core voltage transition ... setup voltage */ static int core_voltage_pre_transition(struct powernow_k8_data *data, - u32 reqvid) + u32 reqvid, u32 reqfid) { u32 rvosteps = data->rvo; u32 savefid = data->currfid; - u32 maxvid, lo; + u32 maxvid, lo, rvomult = 1; dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, " "reqvid 0x%x, rvo 0x%x\n", smp_processor_id(), data->currfid, data->currvid, reqvid, data->rvo); + if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP)) + rvomult = 2; + rvosteps *= rvomult; rdmsr(MSR_FIDVID_STATUS, lo, maxvid); maxvid = 0x1f & (maxvid >> 16); dprintk("ph1 maxvid=0x%x\n", maxvid); @@ -351,7 +354,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, return 1; } - while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) { + while ((rvosteps > 0) && + ((rvomult * data->rvo + data->currvid) > reqvid)) { if (data->currvid == maxvid) { rvosteps = 0; } else { @@ -384,13 +388,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) u32 vcoreqfid, vcocurrfid, vcofiddiff; u32 fid_interval, savevid = data->currvid; - if ((reqfid < HI_FID_TABLE_BOTTOM) && - (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk(KERN_ERR PFX "ph2: illegal lo-lo transition " - "0x%x 0x%x\n", reqfid, data->currfid); - return 1; - } - if (data->currfid == reqfid) { printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", data->currfid); @@ -407,6 +404,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid : vcoreqfid - vcocurrfid; + if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP)) + vcofiddiff = 0; + while (vcofiddiff > 2) { (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); @@ -1081,14 +1081,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, return 0; } - if ((fid < HI_FID_TABLE_BOTTOM) && - (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk(KERN_ERR PFX - "ignoring illegal change in lo freq table-%x to 0x%x\n", - data->currfid, fid); - return 1; - } - dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n", smp_processor_id(), fid, vid); freqs.old = find_khz_freq_from_fid(data->currfid); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index c9c1190b5e1f0..02ce824073cb9 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -215,7 +215,8 @@ struct pst_s { #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg) -static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid); +static int core_voltage_pre_transition(struct powernow_k8_data *data, + u32 reqvid, u32 regfid); static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid); static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); -- GitLab From 9ff1a91c027145a53bec618c8255a7bd0a89794b Mon Sep 17 00:00:00 2001 From: Greg Ungerer <gerg@uclinux.org> Date: Mon, 6 Jul 2009 18:10:25 -0700 Subject: [PATCH 0790/1002] fec: remove extra ";" from definition names Signed-off-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/fec.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 30b7dd671336b..6958d850a6ade 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -46,12 +46,12 @@ #else -#define FEC_ECNTRL; 0x000 /* Ethernet control reg */ -#define FEC_IEVENT; 0x004 /* Interrupt even reg */ -#define FEC_IMASK; 0x008 /* Interrupt mask reg */ -#define FEC_IVEC; 0x00c /* Interrupt vec status reg */ -#define FEC_R_DES_ACTIVE; 0x010 /* Receive descriptor reg */ -#define FEC_X_DES_ACTIVE; 0x01c /* Transmit descriptor reg */ +#define FEC_ECNTRL 0x000 /* Ethernet control reg */ +#define FEC_IEVENT 0x004 /* Interrupt even reg */ +#define FEC_IMASK 0x008 /* Interrupt mask reg */ +#define FEC_IVEC 0x00c /* Interrupt vec status reg */ +#define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ +#define FEC_X_DES_ACTIVE 0x01c /* Transmit descriptor reg */ #define FEC_MII_DATA 0x040 /* MII manage frame reg */ #define FEC_MII_SPEED 0x044 /* MII speed control reg */ #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ -- GitLab From 5ca1ea23c4581f961afaddf1599970e6f05d02dc Mon Sep 17 00:00:00 2001 From: Greg Ungerer <gerg@snapgear.com> Date: Mon, 6 Jul 2009 15:23:34 +0000 Subject: [PATCH 0791/1002] fec: fix definition of 5272 version of FEC_X_DES_ACTIVE register fec: fix definition of 5272 version of FEC_X_DES_ACTIVE register The ColdFire 5272 FEC driver has a different register address map than other users of the FEC driver. And its definition of the FEC_X_DES_ACTIVE register is incorrect, it should be 0x14. The fec interface cannot transmit data with the old value. Signed-off-by: Greg Ungerer <gerg@uclinux.org> ---- Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/fec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 6958d850a6ade..cc47f3f057c74 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -51,7 +51,7 @@ #define FEC_IMASK 0x008 /* Interrupt mask reg */ #define FEC_IVEC 0x00c /* Interrupt vec status reg */ #define FEC_R_DES_ACTIVE 0x010 /* Receive descriptor reg */ -#define FEC_X_DES_ACTIVE 0x01c /* Transmit descriptor reg */ +#define FEC_X_DES_ACTIVE 0x014 /* Transmit descriptor reg */ #define FEC_MII_DATA 0x040 /* MII manage frame reg */ #define FEC_MII_SPEED 0x044 /* MII speed control reg */ #define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ -- GitLab From e33afddca174171a68d57476ead8947476ab9240 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Tue, 7 Jul 2009 11:24:32 +0900 Subject: [PATCH 0792/1002] video: sh_mobile_lcdcfb: Convert to framebuffer_alloc(). All fb_info structures need to be allocated with framebuffer_alloc() due to special initialization. Switch over to it. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/video/sh_mobile_lcdcfb.c | 40 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index da983b720f080..8f24564f77b05 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -31,7 +31,7 @@ struct sh_mobile_lcdc_chan { unsigned long enabled; /* ME and SE in LDCNT2R */ struct sh_mobile_lcdc_chan_cfg cfg; u32 pseudo_palette[PALETTE_NR]; - struct fb_info info; + struct fb_info *info; dma_addr_t dma_handle; struct fb_deferred_io defio; struct scatterlist *sglist; @@ -442,22 +442,22 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) /* set bpp format in PKF[4:0] */ tmp = lcdc_read_chan(ch, LDDFR); tmp &= ~(0x0001001f); - tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0; + tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; lcdc_write_chan(ch, LDDFR, tmp); /* point out our frame buffer */ - lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start); + lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); /* set line size */ - lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length); + lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); /* setup deferred io if SYS bus */ tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; if (ch->ldmt1r_value & (1 << 12) && tmp) { ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; ch->defio.delay = msecs_to_jiffies(tmp); - ch->info.fbdefio = &ch->defio; - fb_deferred_io_init(&ch->info); + ch->info->fbdefio = &ch->defio; + fb_deferred_io_init(ch->info); /* one-shot mode */ lcdc_write_chan(ch, LDSM1R, 1); @@ -503,12 +503,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) * flush frame, and wait for frame end interrupt * clean up deferred io and enable clock */ - if (ch->info.fbdefio) { + if (ch->info->fbdefio) { ch->frame_end = 0; - schedule_delayed_work(&ch->info.deferred_work, 0); + schedule_delayed_work(&ch->info->deferred_work, 0); wait_event(ch->frame_end_wait, ch->frame_end); - fb_deferred_io_cleanup(&ch->info); - ch->info.fbdefio = NULL; + fb_deferred_io_cleanup(ch->info); + ch->info->fbdefio = NULL; sh_mobile_lcdc_clk_on(priv); } @@ -817,9 +817,16 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); for (i = 0; i < j; i++) { - info = &priv->ch[i].info; cfg = &priv->ch[i].cfg; + priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); + if (!priv->ch[i].info) { + dev_err(&pdev->dev, "unable to allocate fb_info\n"); + error = -ENOMEM; + break; + } + + info = priv->ch[i].info; info->fbops = &sh_mobile_lcdc_ops; info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; @@ -872,7 +879,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) for (i = 0; i < j; i++) { struct sh_mobile_lcdc_chan *ch = priv->ch + i; - info = &ch->info; + info = ch->info; if (info->fbdefio) { priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * @@ -915,15 +922,15 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) int i; for (i = 0; i < ARRAY_SIZE(priv->ch); i++) - if (priv->ch[i].info.dev) - unregister_framebuffer(&priv->ch[i].info); + if (priv->ch[i].info->dev) + unregister_framebuffer(priv->ch[i].info); sh_mobile_lcdc_stop(priv); for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { - info = &priv->ch[i].info; + info = priv->ch[i].info; - if (!info->device) + if (!info || !info->device) continue; if (priv->ch[i].sglist) @@ -932,6 +939,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, info->fix.smem_len, info->screen_base, priv->ch[i].dma_handle); fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); } #ifdef CONFIG_HAVE_CLK -- GitLab From 684dcd056178a04374c71459dbd2b18c6d958ef7 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Tue, 7 Jul 2009 11:44:56 +0900 Subject: [PATCH 0793/1002] video: hitfb: Convert to framebuffer_alloc(). Follows the sh_mobile_lcdcfb change. Also fixes up a memory leak with cmap allocation. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/video/hitfb.c | 49 ++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 020db7fc9153a..3ae896d55a58c 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -44,9 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = { .accel = FB_ACCEL_NONE, }; -static u32 pseudo_palette[16]; -static struct fb_info fb_info; - static inline void hitfb_accel_wait(void) { while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; @@ -331,6 +328,8 @@ static struct fb_ops hitfb_ops = { static int __init hitfb_probe(struct platform_device *dev) { unsigned short lcdclor, ldr3, ldvndr; + struct fb_info *info; + int ret; if (fb_get_options("hitfb", NULL)) return -ENODEV; @@ -384,28 +383,50 @@ static int __init hitfb_probe(struct platform_device *dev) break; } - fb_info.fbops = &hitfb_ops; - fb_info.var = hitfb_var; - fb_info.fix = hitfb_fix; - fb_info.pseudo_palette = pseudo_palette; - fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); + if (unlikely(!info)) + return -ENOMEM; + + info->fbops = &hitfb_ops; + info->var = hitfb_var; + info->fix = hitfb_fix; + info->pseudo_palette = info->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; - fb_info.screen_base = (void *)hitfb_fix.smem_start; + info->screen_base = (void *)hitfb_fix.smem_start; - fb_alloc_cmap(&fb_info.cmap, 256, 0); + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (unlikely(ret < 0)) + goto err_fb; - if (register_framebuffer(&fb_info) < 0) - return -EINVAL; + ret = register_framebuffer(info); + if (unlikely(ret < 0)) + goto err; + + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + info->node, info->fix.id); + return 0; + +err: + fb_dealloc_cmap(&info->cmap); +err_fb: + framebuffer_release(info); + return ret; } static int __exit hitfb_remove(struct platform_device *dev) { - return unregister_framebuffer(&fb_info); + struct fb_info *info = platform_get_drvdata(dev); + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + + return 0; } #ifdef CONFIG_PM -- GitLab From 2dbc8a23cc2e677422f6dea991aca4e3d31ab65f Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Tue, 7 Jul 2009 11:50:57 +0900 Subject: [PATCH 0794/1002] video: hitfb: Move over to dev_pm_ops. A trivial update to move hitfb over to dev_pm_ops. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/video/hitfb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 3ae896d55a58c..e7116a6d82d30 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -429,8 +429,7 @@ static int __exit hitfb_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM -static int hitfb_suspend(struct platform_device *dev, pm_message_t state) +static int hitfb_suspend(struct device *dev) { u16 v; @@ -442,7 +441,7 @@ static int hitfb_suspend(struct platform_device *dev, pm_message_t state) return 0; } -static int hitfb_resume(struct platform_device *dev) +static int hitfb_resume(struct device *dev) { u16 v; @@ -456,17 +455,19 @@ static int hitfb_resume(struct platform_device *dev) return 0; } -#endif + +static struct dev_pm_ops hitfb_dev_pm_ops = { + .suspend = hitfb_suspend, + .resume = hitfb_resume, +}; static struct platform_driver hitfb_driver = { .probe = hitfb_probe, .remove = __exit_p(hitfb_remove), -#ifdef CONFIG_PM - .suspend = hitfb_suspend, - .resume = hitfb_resume, -#endif .driver = { .name = "hitfb", + .owner = THIS_MODULE, + .pm = &hitfb_dev_pm_ops, }, }; -- GitLab From dd4da3a55f99efbfd46674ebefdcc2878a57ef2a Mon Sep 17 00:00:00 2001 From: SUGIOKA Toshinobu <sugioka@itonet.co.jp> Date: Tue, 7 Jul 2009 05:32:07 +0000 Subject: [PATCH 0795/1002] serial: sh-sci: fix sci interrupt handler Fix up the error bit handling on SCI ports. Signed-off-by: SUGIOKA Toshinobu <sugioka@itonet.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/serial/sh-sci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 12bd64684f12b..8e2feb5633471 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -716,16 +716,16 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); /* Tx Interrupt */ - if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE)) + if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE)) ret = sci_tx_interrupt(irq, ptr); /* Rx Interrupt */ - if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE)) + if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE)) ret = sci_rx_interrupt(irq, ptr); /* Error Interrupt */ - if ((ssr_status & 0x0080) && err_enabled) + if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) ret = sci_er_interrupt(irq, ptr); /* Break Interrupt */ - if ((ssr_status & 0x0010) && err_enabled) + if ((ssr_status & SCxSR_BRK(port)) && err_enabled) ret = sci_br_interrupt(irq, ptr); return ret; -- GitLab From ebf53f421308c2f59c9bcbad4c5c297a0d00199a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 6 Jul 2009 08:57:53 +0300 Subject: [PATCH 0796/1002] UBI: fix NOR flash recovery This commit fixes NOR flash recovery issues observed with Spansion S29GL512N NOR. When NOR erases, it first fills PEBs with zeroes, then sets all bytes to 0xFF. Filling with zeroes starts from the end of the PEB. And when power is cut, this results in PEBs containing correct EC and VID headers but corrupted with zeros at the end. This confuses UBI and it mistakinly accepts these PEBs and associate them with LEBs. Fis this issue by zeroing EC and VID magics before erasing PEBs, to make UBI later refuse zem. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/build.c | 5 ++++ drivers/mtd/ubi/io.c | 58 +++++++++++++++++++++++++++++++++++++++-- drivers/mtd/ubi/ubi.h | 4 ++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index db0b9cb64c6ce..e1f7d0a78b9d5 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi) if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) ubi->bad_allowed = 1; + if (ubi->mtd->type == MTD_NORFLASH) { + ubi_assert(ubi->mtd->writesize == 1); + ubi->nor_flash = 1; + } + ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 1ea14218de021..c3bd2e34c6420 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -266,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, addr = (loff_t)pnum * ubi->peb_size + offset; err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); if (err) { - ubi_err("error %d while writing %d bytes to PEB %d:%d, written" - " %zd bytes", err, len, pnum, offset, written); + ubi_err("error %d while writing %d bytes to PEB %d:%d, written " + "%zd bytes", err, len, pnum, offset, written); ubi_dbg_dump_stack(); } else ubi_assert(written == len); @@ -453,6 +453,54 @@ static int torture_peb(struct ubi_device *ubi, int pnum) return err; } +/** + * nor_erase_prepare - prepare a NOR flash PEB for erasure. + * @ubi: UBI device description object + * @pnum: physical eraseblock number to prepare + * + * NOR flash, or at least some of them, have peculiar embedded PEB erasure + * algorithm: the PEB is first filled with zeroes, then it is erased. And + * filling with zeroes starts from the end of the PEB. This was observed with + * Spansion S29GL512N NOR flash. + * + * This means that in case of a power cut we may end up with intact data at the + * beginning of the PEB, and all zeroes at the end of PEB. In other words, the + * EC and VID headers are OK, but a large chunk of data at the end of PEB is + * zeroed. This makes UBI mistakenly treat this PEB as used and associate it + * with an LEB, which leads to subsequent failures (e.g., UBIFS fails). + * + * This function is called before erasing NOR PEBs and it zeroes out EC and VID + * magic numbers in order to invalidate them and prevent the failures. Returns + * zero in case of success and a negative error code in case of failure. + */ +static int nor_erase_prepare(struct ubi_device *ubi, int pnum) +{ + int err; + size_t written; + loff_t addr; + uint32_t data = 0; + + addr = (loff_t)pnum * ubi->peb_size; + err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data); + if (err) { + ubi_err("error %d while writing 4 bytes to PEB %d:0, written " + "%zd bytes", err, pnum, 0, written); + ubi_dbg_dump_stack(); + return err; + } + + addr += ubi->vid_hdr_aloffset; + err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data); + if (err) { + ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " + "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); + ubi_dbg_dump_stack(); + return err; + } + + return 0; +} + /** * ubi_io_sync_erase - synchronously erase a physical eraseblock. * @ubi: UBI device description object @@ -484,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) return -EROFS; } + if (ubi->nor_flash) { + err = nor_erase_prepare(ubi, pnum); + if (err) + return err; + } + if (torture) { ret = torture_peb(ubi, pnum); if (ret < 0) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 64604e8809eca..6a5fe96337836 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -373,6 +373,7 @@ struct ubi_wl_entry; * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or * not + * @nor_flash: non-zero if working on top of NOR flash * @mtd: MTD device descriptor * * @peb_buf1: a buffer of PEB size used for different purposes @@ -454,7 +455,8 @@ struct ubi_device { int vid_hdr_offset; int vid_hdr_aloffset; int vid_hdr_shift; - int bad_allowed; + unsigned int bad_allowed:1; + unsigned int nor_flash:1; struct mtd_info *mtd; void *peb_buf1; -- GitLab From 7afdbf23c3acdec3eaf1b94f87132fff3d81ce73 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Tue, 7 Jul 2009 10:23:43 +0200 Subject: [PATCH 0797/1002] signals: declare sys_rt_tgsigqueueinfo in syscalls.h sys_rt_tgsigqueueinfo needs to be declared in linux/syscalls.h so that architectures defining the system call table in C can reference it. Signed-off-by: Arnd Bergmann <arnd@arndb.de> LKML-Reference: <200907071023.44008.arnd@arndb.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- include/linux/syscalls.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index fa4242cdade86..80de7003d8c23 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -321,6 +321,8 @@ asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, siginfo_t __user *uinfo, const struct timespec __user *uts, size_t sigsetsize); +asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, + siginfo_t __user *uinfo); asmlinkage long sys_kill(int pid, int sig); asmlinkage long sys_tgkill(int tgid, int pid, int sig); asmlinkage long sys_tkill(int pid, int sig); -- GitLab From 55d1d6c1ef630dddd3cb5354c32a5aca954399e8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Tue, 7 Jul 2009 13:39:03 +0200 Subject: [PATCH 0798/1002] ALSA: hda - Clean up VT170x dig-in initialization code Minor clean up for initializing the digital-in pin. No functional changes. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_via.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 8e004fb6961ad..c4ddbbc6231ac 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -211,6 +211,7 @@ struct via_spec { unsigned int num_adc_nids; hda_nid_t *adc_nids; hda_nid_t dig_in_nid; + hda_nid_t dig_in_pin; /* capture source */ const struct hda_input_mux *input_mux; @@ -998,25 +999,11 @@ static int via_init(struct hda_codec *codec) /* Lydia Add for EAPD enable */ if (!spec->dig_in_nid) { /* No Digital In connection */ - if (IS_VT1708_VENDORID(codec->vendor_id)) { - snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0, + if (spec->dig_in_pin) { + snd_hda_codec_write(codec, spec->dig_in_pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0, - AC_VERB_SET_EAPD_BTLENABLE, 0x02); - } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) || - IS_VT1709_6CH_VENDORID(codec->vendor_id)) { - snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_OUT); - snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0, - AC_VERB_SET_EAPD_BTLENABLE, 0x02); - } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) || - IS_VT1708B_4CH_VENDORID(codec->vendor_id)) { - snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_OUT); - snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0, + snd_hda_codec_write(codec, spec->dig_in_pin, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x02); } } else /* enable SPDIF-input pin */ @@ -1326,6 +1313,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) if (spec->autocfg.dig_outs) spec->multiout.dig_out_nid = VT1708_DIGOUT_NID; + spec->dig_in_pin = VT1708_DIGIN_PIN; if (spec->autocfg.dig_in_pin) spec->dig_in_nid = VT1708_DIGIN_NID; @@ -1799,6 +1787,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) if (spec->autocfg.dig_outs) spec->multiout.dig_out_nid = VT1709_DIGOUT_NID; + spec->dig_in_pin = VT1709_DIGIN_PIN; if (spec->autocfg.dig_in_pin) spec->dig_in_nid = VT1709_DIGIN_NID; @@ -2344,6 +2333,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) if (spec->autocfg.dig_outs) spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID; + spec->dig_in_pin = VT1708B_DIGIN_PIN; if (spec->autocfg.dig_in_pin) spec->dig_in_nid = VT1708B_DIGIN_NID; -- GitLab From d3a11e601a51291fbdd40c47f6af6769b6e905ef Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Tue, 7 Jul 2009 13:43:35 +0200 Subject: [PATCH 0799/1002] ALSA: hda - Add missing EAPD initialization for VIA codecs If the output pin is used and EAPD capability is present, turn on the EAPD bit. This fixes the silent output problem on ASUS laptops with VT1708S codec. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_via.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c4ddbbc6231ac..322e10272474d 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -320,6 +320,9 @@ static void via_auto_set_output_and_unmute(struct hda_codec *codec, pin_type); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_EAPD_BTLENABLE, 0x02); } -- GitLab From c9568fddf130cfa0d61eb1205342dbc5ab0ed394 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:03 +0200 Subject: [PATCH 0800/1002] [S390] sclp: fix compile error for !SCLP_CONSOLE Define an empty static inline version of sclp_console_pm_event() to fix the build error below for !SCLP_CONSOLE. drivers/s390/built-in.o: In function `sclp_rw_pm_event': sclp_rw.c:(.text+0x12f68): undefined reference to `sclp_console_pm_event' Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- drivers/s390/char/sclp_rw.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/s390/char/sclp_rw.h b/drivers/s390/char/sclp_rw.h index 85f491ea929c0..7a7bfc947d97e 100644 --- a/drivers/s390/char/sclp_rw.h +++ b/drivers/s390/char/sclp_rw.h @@ -92,5 +92,10 @@ void sclp_set_columns(struct sclp_buffer *, unsigned short); void sclp_set_htab(struct sclp_buffer *, unsigned short); int sclp_chars_in_buffer(struct sclp_buffer *); +#ifdef CONFIG_SCLP_CONSOLE void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event); +#else +static inline void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) { } +#endif + #endif /* __SCLP_RW_H__ */ -- GitLab From 9935774217afd4cdda81ffd70e56dc6406710b06 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:04 +0200 Subject: [PATCH 0801/1002] [S390] monreader: fix dev_set_drvdata conversion Fix this: drivers/s390/char/monreader.c: In function 'mon_open': drivers/s390/char/monreader.c:323: warning: passing argument 1 of 'dev_set_drvdata' from incompatible pointer type include/linux/device.h:457: note: expected 'struct device *' but argument is of type 'struct device **' drivers/s390/char/monreader.c: In function 'monreader_freeze': drivers/s390/char/monreader.c:466: warning: passing argument 1 of 'dev_get_drvdata' from incompatible pointer type include/linux/device.h:452: note: expected 'const struct device *' but argument is of type 'struct device **' Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- drivers/s390/char/monreader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 7892550d79328..3234e90bd7f99 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c @@ -320,7 +320,7 @@ static int mon_open(struct inode *inode, struct file *filp) goto out_path; } filp->private_data = monpriv; - dev_set_drvdata(&monreader_device, monpriv); + dev_set_drvdata(monreader_device, monpriv); unlock_kernel(); return nonseekable_open(inode, filp); @@ -463,7 +463,7 @@ static struct miscdevice mon_dev = { *****************************************************************************/ static int monreader_freeze(struct device *dev) { - struct mon_private *monpriv = dev_get_drvdata(&dev); + struct mon_private *monpriv = dev_get_drvdata(dev); int rc; if (!monpriv) -- GitLab From bb8c29caffdda55d3df0315ff2485f7df7290b1d Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:05 +0200 Subject: [PATCH 0802/1002] [S390] udelay: disable lockdep to avoid false positives Our udelay implementation enables interrupts to receive a special timer interrupt regardless of the context it is called from. This might lead to false positive lockdep reports. Since lockdep isn't aware of the fact that only a single interrupt source is enabled it warns about possible deadlocks that in reality won't happen, like the one below. To fix this disable lockdep before enabling interrupts. [ 254.040888] ================================= [ 254.040904] [ INFO: inconsistent lock state ] [ 254.040910] 2.6.30 #9 [ 254.040914] --------------------------------- [ 254.040920] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. [ 254.040927] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 254.040934] (sch->lock){?.-...}, at: [<00000000002e4778>] ccw_device_timeout+0x48/0x2f0 [ 254.040961] {IN-HARDIRQ-W} state was registered at: [ 254.040969] [<0000000000096f74>] __lock_acquire+0x9d4/0x188c [ 254.040985] [<0000000000097f68>] lock_acquire+0x13c/0x16c [ 254.040998] [<00000000004527e0>] _spin_lock+0x74/0xb8 [ 254.041016] [<0000000000457eb2>] do_IRQ+0xde/0x208 [ 254.041031] [<000000000002d190>] io_return+0x0/0x8 [ 254.041049] [<0000000000029faa>] vtime_stop_cpu+0xbe/0x114 [ 254.041066] irq event stamp: 259629 [ 254.041076] hardirqs last enabled at (259628): [<000000000045238e>] _spin_unlock_irq+0x5e/0x9c [ 254.041095] hardirqs last disabled at (259629): [<000000000045292e>] _spin_lock_irq+0x4a/0xc4 [ 254.041126] softirqs last enabled at (259614): [<000000000006500e>] __do_softirq+0x296/0x2b0 [ 254.041137] softirqs last disabled at (259619): [<0000000000024cf6>] do_softirq+0x102/0x108 [ 254.041147] [ 254.041148] other info that might help us debug this: [ 254.041153] 2 locks held by swapper/0: [ 254.041157] #0: (&priv->timer){+.-...}, at: [<000000000006bf9a>] run_timer_softirq+0x19a/0x340 [ 254.041170] #1: (sch->lock){?.-...}, at: [<00000000002e4778>] ccw_device_timeout+0x48/0x2f0 [ 254.041182] [ 254.041310] Call Trace: [ 254.041313] ([<00000000000174fc>] show_trace+0x16c/0x170) [ 254.041321] [<0000000000017578>] show_stack+0x78/0x104 [ 254.041327] [<000000000044d0ca>] dump_stack+0xc6/0xd4 [ 254.041342] [<00000000000949b4>] print_usage_bug+0x1c8/0x1fc [ 254.041353] [<0000000000094e8a>] mark_lock+0x4a2/0x670 [ 254.041364] [<00000000000950e2>] mark_held_locks+0x8a/0xb4 [ 254.041375] [<0000000000095398>] trace_hardirqs_on_caller+0x74/0x1ac [ 254.041388] [<00000000000954fa>] trace_hardirqs_on+0x2a/0x38 [ 254.041402] [<000000000025f1ec>] __udelay_disabled+0xac/0xfc [ 254.041419] [<000000000025f432>] __udelay+0x12a/0x148 [ 254.041433] [<00000000002d64d8>] cio_commit_config+0x170/0x290 [ 254.041451] [<00000000002d6978>] cio_disable_subchannel+0x120/0x1cc [ 254.041468] [<00000000002e32a4>] ccw_device_recog_done+0x54/0x2f4 [ 254.041485] [<00000000002e3638>] ccw_device_sense_id_done+0x50/0x90 [ 254.041508] [<00000000002e615a>] snsid_callback+0xfa/0x3a8 [ 254.041515] [<00000000002dd96c>] ccwreq_stop+0x80/0x90 [ 254.041523] [<00000000002dda8e>] ccw_request_timeout+0xc2/0xd0 [ 254.041530] [<00000000002e2f70>] ccw_device_request_event+0x58/0x90 [ 254.041537] [<00000000002e47ae>] ccw_device_timeout+0x7e/0x2f0 [ 254.041555] [<000000000006c02a>] run_timer_softirq+0x22a/0x340 [ 254.041566] [<0000000000064eb0>] __do_softirq+0x138/0x2b0 [ 254.041578] [<0000000000024cf6>] do_softirq+0x102/0x108 [ 254.041590] [<00000000000647ce>] irq_exit+0xee/0x114 [ 254.041603] [<0000000000457d88>] do_extint+0x130/0x17c [ 254.041617] [<000000000002d41e>] ext_no_vtime+0x1e/0x22 [ 254.041631] [<0000000000029faa>] vtime_stop_cpu+0xbe/0x114 [ 254.041646] ([<0000000000029f58>] vtime_stop_cpu+0x6c/0x114) [ 254.041662] [<000000000001d842>] cpu_idle+0x122/0x1c0 [ 254.041679] [<00000000004482c6>] start_secondary+0xce/0xe0 [ 254.041696] [<0000000000000000>] 0x0 [ 254.041715] [<0000000000000000>] 0x0 [ 254.041745] INFO: lockdep is turned off. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/lib/delay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c index 3f5f680726ed1..97c1eca83cc24 100644 --- a/arch/s390/lib/delay.c +++ b/arch/s390/lib/delay.c @@ -36,9 +36,11 @@ static void __udelay_disabled(unsigned long usecs) cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; __ctl_load(cr0 , 0, 0); mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; + lockdep_off(); trace_hardirqs_on(); __load_psw_mask(mask); local_irq_disable(); + lockdep_on(); __ctl_load(cr0_saved, 0, 0); local_tick_enable(clock_saved); set_clock_comparator(S390_lowcore.clock_comparator); -- GitLab From aeec92ca3a1d5ca96efe76988fd4df943a90300d Mon Sep 17 00:00:00 2001 From: Stefan Haberland <stefan.haberland@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:06 +0200 Subject: [PATCH 0803/1002] [S390] dasd: correct debugfeature sense dump remove loop, add some debug data and use get_sense function Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- drivers/s390/block/dasd_eckd.c | 45 +++++++++------------------------- drivers/s390/block/dasd_erp.c | 2 +- drivers/s390/block/dasd_fba.c | 25 ++++++++++--------- drivers/s390/block/dasd_int.h | 3 +-- 4 files changed, 27 insertions(+), 48 deletions(-) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index f8b1f04f26b8e..c11770f5b368f 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1696,8 +1696,7 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, DBF_DEV_EVENT(DBF_ERR, device, "%s", "unsolicited interrupt received " "(sense available)"); - device->discipline->dump_sense_dbf(device, NULL, irb, - "unsolicited"); + device->discipline->dump_sense_dbf(device, irb, "unsolicited"); } dasd_schedule_device_bh(device); @@ -2941,42 +2940,20 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) } static void -dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, - struct irb *irb, char *reason) +dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct irb *irb, + char *reason) { u64 *sense; - int sl; - struct tsb *tsb; - sense = NULL; - tsb = NULL; - if (req && scsw_is_tm(&req->irb.scsw)) { - if (irb->scsw.tm.tcw) - tsb = tcw_get_tsb( - (struct tcw *)(unsigned long)irb->scsw.tm.tcw); - if (tsb && (irb->scsw.tm.fcxs == 0x01)) { - switch (tsb->flags & 0x07) { - case 1: /* tsa_iostat */ - sense = (u64 *)tsb->tsa.iostat.sense; - break; - case 2: /* ts_ddpc */ - sense = (u64 *)tsb->tsa.ddpc.sense; - break; - case 3: /* tsa_intrg */ - break; - } - } - } else { - if (irb->esw.esw0.erw.cons) - sense = (u64 *)irb->ecw; - } + sense = (u64 *) dasd_get_sense(irb); if (sense) { - for (sl = 0; sl < 4; sl++) { - DBF_DEV_EVENT(DBF_EMERG, device, - "%s: %016llx %016llx %016llx %016llx", - reason, sense[0], sense[1], sense[2], - sense[3]); - } + DBF_DEV_EVENT(DBF_EMERG, device, + "%s: %s %02x%02x%02x %016llx %016llx %016llx " + "%016llx", reason, + scsw_is_tm(&irb->scsw) ? "t" : "c", + scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw), + scsw_dstat(&irb->scsw), sense[0], sense[1], + sense[2], sense[3]); } else { DBF_DEV_EVENT(DBF_EMERG, device, "%s", "SORRY - NO VALID SENSE AVAILABLE\n"); diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index d970ce2814bed..cb8f9cef74290 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c @@ -172,7 +172,7 @@ dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb) device = cqr->startdev; /* dump sense data to s390 debugfeature*/ if (device->discipline && device->discipline->dump_sense_dbf) - device->discipline->dump_sense_dbf(device, cqr, irb, "log"); + device->discipline->dump_sense_dbf(device, irb, "log"); } EXPORT_SYMBOL(dasd_log_sense_dbf); diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index e21ee735f9267..31849ad5e59fe 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -241,7 +241,7 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device, /* check for unsolicited interrupts */ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "unsolicited interrupt received"); - device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited"); + device->discipline->dump_sense_dbf(device, irb, "unsolicited"); dasd_schedule_device_bh(device); return; }; @@ -444,17 +444,20 @@ dasd_fba_fill_info(struct dasd_device * device, } static void -dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req, - struct irb *irb, char *reason) +dasd_fba_dump_sense_dbf(struct dasd_device *device, struct irb *irb, + char *reason) { - int sl; - if (irb->esw.esw0.erw.cons) { - for (sl = 0; sl < 4; sl++) { - DBF_DEV_EVENT(DBF_EMERG, device, - "%s: %08x %08x %08x %08x", - reason, irb->ecw[8 * 0], irb->ecw[8 * 1], - irb->ecw[8 * 2], irb->ecw[8 * 3]); - } + u64 *sense; + + sense = (u64 *) dasd_get_sense(irb); + if (sense) { + DBF_DEV_EVENT(DBF_EMERG, device, + "%s: %s %02x%02x%02x %016llx %016llx %016llx " + "%016llx", reason, + scsw_is_tm(&irb->scsw) ? "t" : "c", + scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw), + scsw_dstat(&irb->scsw), sense[0], sense[1], + sense[2], sense[3]); } else { DBF_DEV_EVENT(DBF_EMERG, device, "%s", "SORRY - NO VALID SENSE AVAILABLE\n"); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index fd63b2f2bda9b..b699ca356ac55 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -284,8 +284,7 @@ struct dasd_discipline { dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *); void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *, struct irb *); - void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *, - struct irb *, char *); + void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *); void (*handle_unsolicited_interrupt) (struct dasd_device *, struct irb *); -- GitLab From 81088819d588ba4d2dce3bf083fafc91974b14e0 Mon Sep 17 00:00:00 2001 From: Frank Munzert <munzert@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:07 +0200 Subject: [PATCH 0804/1002] [S390] shutdown actions: save/return rc from init function We always returned -EINVAL when setting of a shutdown action failed. This was misleading, if for example the hardware did not support the shutdown action. Now we save each shutdown action's init return code and return it when the action is being set. Signed-off-by: Frank Munzert <munzert@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/kernel/ipl.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index b8bf4b1400652..371a2d88f4ac7 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -70,6 +70,7 @@ struct shutdown_action { char *name; void (*fn) (struct shutdown_trigger *trigger); int (*init) (void); + int init_rc; }; static char *ipl_type_str(enum ipl_type type) @@ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, int i; for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { - if (!shutdown_actions_list[i]) - continue; if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { - trigger->action = shutdown_actions_list[i]; - return len; + if (shutdown_actions_list[i]->init_rc) { + return shutdown_actions_list[i]->init_rc; + } else { + trigger->action = shutdown_actions_list[i]; + return len; + } } } return -EINVAL; @@ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void) for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { if (!shutdown_actions_list[i]->init) continue; - if (shutdown_actions_list[i]->init()) - shutdown_actions_list[i] = NULL; + shutdown_actions_list[i]->init_rc = + shutdown_actions_list[i]->init(); } } -- GitLab From 2651fa2bcb1a7b06793441d50dcbf98efda592c6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:08 +0200 Subject: [PATCH 0805/1002] [S390] perf_counter build fix Add PERF_COUNTER_INDEX_OFFSET define to fix this build bug: kernel/perf_counter.c: In function 'perf_counter_index': kernel/perf_counter.c:1889: error: 'PERF_COUNTER_INDEX_OFFSET' undeclared Same fix as for FRV since s390 doesn't support hw counters. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/include/asm/perf_counter.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/include/asm/perf_counter.h b/arch/s390/include/asm/perf_counter.h index a7205a3828cb1..7015188c2cc27 100644 --- a/arch/s390/include/asm/perf_counter.h +++ b/arch/s390/include/asm/perf_counter.h @@ -6,3 +6,5 @@ static inline void set_perf_counter_pending(void) {} static inline void clear_perf_counter_pending(void) {} + +#define PERF_COUNTER_INDEX_OFFSET 0 -- GitLab From 5075baca2e95840d76210c3cfda56134007462c9 Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:09 +0200 Subject: [PATCH 0806/1002] [S390] add __ucmpdi2() helper function Provide __ucmpdi2() helper function on 31 bit so we don't run again and again in compile errors like this one: kernel/built-in.o: In function `T.689': perf_counter.c:(.text+0x56c86): undefined reference to `__ucmpdi2' Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/lib/Makefile | 2 +- arch/s390/lib/ucmpdi2.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 arch/s390/lib/ucmpdi2.c diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index ab6735df2d215..97975ec7a2747 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -3,6 +3,6 @@ # lib-y += delay.o string.o uaccess_std.o uaccess_pt.o -obj-$(CONFIG_32BIT) += div64.o qrnnd.o +obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/arch/s390/lib/ucmpdi2.c b/arch/s390/lib/ucmpdi2.c new file mode 100644 index 0000000000000..3e05ff5325824 --- /dev/null +++ b/arch/s390/lib/ucmpdi2.c @@ -0,0 +1,26 @@ +#include <linux/module.h> + +union ull_union { + unsigned long long ull; + struct { + unsigned int high; + unsigned int low; + } ui; +}; + +int __ucmpdi2(unsigned long long a, unsigned long long b) +{ + union ull_union au = {.ull = a}; + union ull_union bu = {.ull = b}; + + if (au.ui.high < bu.ui.high) + return 0; + else if (au.ui.high > bu.ui.high) + return 2; + if (au.ui.low < bu.ui.low) + return 0; + else if (au.ui.low > bu.ui.low) + return 2; + return 1; +} +EXPORT_SYMBOL(__ucmpdi2); -- GitLab From fca3e357d5de31e484c3e0ec7f356e4fc488eb7f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky <schwidefsky@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:10 +0200 Subject: [PATCH 0807/1002] [S390] set SCHED_OMIT_FRAME_POINTER for s390 The frame pointer is useless for s390 in the sched.c code. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e577839f3073e..4cd12b5202af4 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -96,6 +96,10 @@ config S390 select INIT_ALL_POSSIBLE select HAVE_PERF_COUNTERS +config SCHED_OMIT_FRAME_POINTER + bool + default y + source "init/Kconfig" source "kernel/Kconfig.freezer" -- GitLab From 2c48c4d631970b70d60a4f926b0f68f194a0d559 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger <borntraeger@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:11 +0200 Subject: [PATCH 0808/1002] [S390] improve suspend/resume error messages From: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- drivers/s390/block/dcssblk.c | 7 ++++--- drivers/s390/block/xpram.c | 2 +- drivers/s390/char/vmwatchdog.c | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 016f9e9d25918..d34617682a629 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -964,7 +964,8 @@ static int dcssblk_freeze(struct device *dev) break; } if (rc) - pr_err("Suspend failed because device %s is writeable.\n", + pr_err("Suspending the system failed because DCSS device %s " + "is writable\n", dev_info->segment_name); return rc; } @@ -987,8 +988,8 @@ static int dcssblk_restore(struct device *dev) goto out_panic; } if (start != entry->start || end != entry->end) { - pr_err("Mismatch of start / end address after " - "resuming device %s\n", + pr_err("The address range of DCSS %s changed " + "while the system was suspended\n", entry->segment_name); goto out_panic; } diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 2e9e1ecd6d82b..db442cd6621ec 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -443,7 +443,7 @@ static int xpram_validate_checksums(void) */ static void xpram_resume_error(const char *message) { - pr_err("Resume error: %s\n", message); + pr_err("Resuming the system failed: %s\n", message); panic("xpram resume error\n"); } diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c index cb7854c10c047..f2bc287b69e4e 100644 --- a/drivers/s390/char/vmwatchdog.c +++ b/drivers/s390/char/vmwatchdog.c @@ -250,14 +250,14 @@ static int vmwdt_resume(void) static int vmwdt_suspend(void) { if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) { - pr_err("The watchdog is in use. " - "This prevents hibernation or suspend.\n"); + pr_err("The system cannot be suspended while the watchdog" + " is in use\n"); return NOTIFY_BAD; } if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) { clear_bit(VMWDT_OPEN, &vmwdt_is_open); - pr_err("The watchdog is running. " - "This prevents hibernation or suspend.\n"); + pr_err("The system cannot be suspended while the watchdog" + " is running\n"); return NOTIFY_BAD; } return NOTIFY_DONE; -- GitLab From 25ca1251dc55673da1f3c6ddc1bf93fbb7fc83fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens <heiko.carstens@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:12 +0200 Subject: [PATCH 0809/1002] [S390] add generic atomic64 support for 31 bit Performance counters need 64 bit atomic operations. To keep the patch small we use the simple generic atomic64_t implementation. The native implementation follows with the next kernel. Fixes this build bug: In file included from kernel/sched.c:42: include/linux/perf_counter.h:427: error: expected specifier-qualifier-list before 'atomic64_t' Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/Kconfig | 1 + arch/s390/include/asm/atomic.h | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 4cd12b5202af4..f46a1b50ddeec 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -95,6 +95,7 @@ config S390 select HAVE_ARCH_TRACEHOOK select INIT_ALL_POSSIBLE select HAVE_PERF_COUNTERS + select GENERIC_ATOMIC64 if !64BIT config SCHED_OMIT_FRAME_POINTER bool diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index fca9dffcc669b..c7d0abfb0f008 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -268,7 +268,12 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) #undef __CSG_LOOP -#endif + +#else /* __s390x__ */ + +#include <asm-generic/atomic64.h> + +#endif /* __s390x__ */ #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() -- GitLab From 07606309ff5a9136e340b9ca87c831650c1ec47a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky <schwidefsky@de.ibm.com> Date: Tue, 7 Jul 2009 16:37:13 +0200 Subject: [PATCH 0810/1002] [S390] define KTIME_SCALAR for 32-bit s390 32-bit s390 has efficient support for 64/32-bit conversions, define KTIME_SCALAR to enable the use of the plain scalar nanosecond based representation of ktime. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> --- arch/s390/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f46a1b50ddeec..2ae5d72f47eda 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -121,6 +121,9 @@ config 32BIT bool default y if !64BIT +config KTIME_SCALAR + def_bool 32BIT + config SMP bool "Symmetric multi-processing support" ---help--- -- GitLab From d01730d74d2b0155da50d44555001706294014f7 Mon Sep 17 00:00:00 2001 From: Jiaying Zhang <jiayingz@google.com> Date: Tue, 7 Jul 2009 18:15:21 +0200 Subject: [PATCH 0811/1002] quota: Fix possible deadlock during parallel quotaon and quotaoff The following test script triggers a deadlock on ext2 filesystem: while true; do quotaon /dev/hda >&/dev/null; usleep $RANDOM; done & while true; do quotaoff /dev/hda >&/dev/null; usleep $RANDOM; done & I found there is a potential deadlock between quotaon and quotaoff (or quotasync). Basically, all of quotactl operations need to be protected by dqonoff_mutex. vfs_quota_off and vfs_quota_sync also call sb->s_op->quota_write that needs to grab the i_mutex of the quota file. But in vfs_quota_on_inode (called from quotaon operation), the current code tries to grab the i_mutex of the quota file first before getting quonoff_mutex. Reverse the order in which we take locks in vfs_quota_on_inode(). Jan Kara: Changed changelog to be more readable, made lockdep happy with I_MUTEX_QUOTA. Signed-off-by: Jiaying Zhang <jiayingz@google.com> Signed-off-by: Jan Kara <jack@suse.cz> --- fs/quota/dquot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 607c579e5eca0..70f36c043d623 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2042,8 +2042,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, * changes */ invalidate_bdev(sb->s_bdev); } - mutex_lock(&inode->i_mutex); mutex_lock(&dqopt->dqonoff_mutex); + mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); if (sb_has_quota_loaded(sb, type)) { error = -EBUSY; goto out_lock; @@ -2094,7 +2094,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, dqopt->files[type] = NULL; iput(inode); out_lock: - mutex_unlock(&dqopt->dqonoff_mutex); if (oldflags != -1) { down_write(&dqopt->dqptr_sem); /* Set the flags back (in the case of accidental quotaon() @@ -2104,6 +2103,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, up_write(&dqopt->dqptr_sem); } mutex_unlock(&inode->i_mutex); + mutex_unlock(&dqopt->dqonoff_mutex); out_fmt: put_quota_format(fmt); -- GitLab From 337b9d02b4873ceac91565272545fb6fd446d939 Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Tue, 7 Jul 2009 18:18:59 +0200 Subject: [PATCH 0812/1002] ALSA: hda - Fix capture source selection in patch_via.c The fixed widget NIDs in patch_via.c seem wrong for some codecs, and it resulted in the invalid capture source selection. This patch adds the code to parse the topology instead of using fixed numbers in order to get the right MUX widget id corresponding to the ADCs. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_via.c | 54 +++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 322e10272474d..38db45964228a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -210,6 +210,7 @@ struct via_spec { /* capture */ unsigned int num_adc_nids; hda_nid_t *adc_nids; + hda_nid_t mux_nids[3]; hda_nid_t dig_in_nid; hda_nid_t dig_in_pin; @@ -393,25 +394,11 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int vendor_id = codec->vendor_id; - /* AIW0 lydia 060801 add for correct sw0 input select */ - if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0)) - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - 0x18, &spec->cur_mux[adc_idx]); - else if ((IS_VT1709_10CH_VENDORID(vendor_id) || - IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0)) - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - 0x19, &spec->cur_mux[adc_idx]); - else if ((IS_VT1708B_8CH_VENDORID(vendor_id) || - IS_VT1708B_4CH_VENDORID(vendor_id)) && (adc_idx == 0)) - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - 0x17, &spec->cur_mux[adc_idx]); - else if (IS_VT1702_VENDORID(vendor_id) && (adc_idx == 0)) - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - 0x13, &spec->cur_mux[adc_idx]); - else - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->adc_nids[adc_idx], - &spec->cur_mux[adc_idx]); + if (!spec->mux_nids[adc_idx]) + return -EINVAL; + return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, + spec->mux_nids[adc_idx], + &spec->cur_mux[adc_idx]); } static int via_independent_hp_info(struct snd_kcontrol *kcontrol, @@ -1343,6 +1330,29 @@ static int via_auto_init(struct hda_codec *codec) return 0; } +static int get_mux_nids(struct hda_codec *codec) +{ + struct via_spec *spec = codec->spec; + hda_nid_t nid, conn[8]; + unsigned int type; + int i, n; + + for (i = 0; i < spec->num_adc_nids; i++) { + nid = spec->adc_nids[i]; + while (nid) { + n = snd_hda_get_connections(codec, nid, conn, + ARRAY_SIZE(conn)); + if (n <= 0) + break; + if (n > 1) { + spec->mux_nids[i] = nid; + break; + } + nid = conn[0]; + } + } +} + static int patch_vt1708(struct hda_codec *codec) { struct via_spec *spec; @@ -1851,6 +1861,7 @@ static int patch_vt1709_10ch(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1709_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1709_capture_mixer; spec->num_mixers++; } @@ -1944,6 +1955,7 @@ static int patch_vt1709_6ch(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1709_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1709_capture_mixer; spec->num_mixers++; } @@ -2397,6 +2409,7 @@ static int patch_vt1708B_8ch(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1708B_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1708B_capture_mixer; spec->num_mixers++; } @@ -2448,6 +2461,7 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1708B_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1708B_capture_mixer; spec->num_mixers++; } @@ -2882,6 +2896,7 @@ static int patch_vt1708S(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1708S_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1708S_capture_mixer; spec->num_mixers++; } @@ -3199,6 +3214,7 @@ static int patch_vt1702(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1702_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids); + get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1702_capture_mixer; spec->num_mixers++; } -- GitLab From 1f5fc70a250cc18f066072119e9fbbc20dad865f Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Sat, 20 Jun 2009 12:31:11 +0200 Subject: [PATCH 0813/1002] Wireless: nl80211, fix lock imbalance Don't forget to unlock cfg80211_mutex in one fail path of nl80211_set_wiphy. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/wireless/nl80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 241bddd0b4f19..43bdb1372caee 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -447,6 +447,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) rdev = __cfg80211_drv_from_info(info); if (IS_ERR(rdev)) { + mutex_unlock(&cfg80211_mutex); result = PTR_ERR(rdev); goto unlock; } -- GitLab From fd4973c56f8d9baac8d269791a90e5119ce30a0e Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Sat, 20 Jun 2009 12:58:11 -0500 Subject: [PATCH 0814/1002] b43/b43legacy: fix radio LED initialization Fix condition in which radio LED did not initialize correctly, and remove 4 compilation warnings. After the recent changes in rfkill, the radio LED used by b43/b43legacy did not always initialize correctly. Both b43 and b43legacy used the deprecated variable radio_enabled in struct ieee80211_conf. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 7 +++++-- drivers/net/wireless/b43legacy/b43legacy.h | 1 + drivers/net/wireless/b43legacy/main.c | 7 +++++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f580c2812d918..40448067e4cca 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -648,6 +648,7 @@ struct b43_wl { u8 nr_devs; bool radiotap_enabled; + bool radio_enabled; /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6456afebdba10..e71c8d9cd706e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3497,8 +3497,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); - if (!!conf->radio_enabled != phy->radio_on) { - if (conf->radio_enabled) { + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { b43_software_rfkill(dev, false); b43info(dev->wl, "Radio turned on by software\n"); if (!dev->radio_hw_enable) { @@ -4339,6 +4339,7 @@ static int b43_op_start(struct ieee80211_hw *hw) wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; wl->beacon_templates_virgin = 1; + wl->radio_enabled = 1; mutex_lock(&wl->mutex); @@ -4378,6 +4379,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) if (b43_status(dev) >= B43_STAT_STARTED) b43_wireless_core_stop(dev); b43_wireless_core_exit(dev); + wl->radio_enabled = 0; mutex_unlock(&wl->mutex); cancel_work_sync(&(wl->txpower_adjust_work)); @@ -4560,6 +4562,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) B43_WARN_ON(1); dev->phy.gmode = have_2ghz_phy; + dev->phy.radio_on = 1; tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; b43_wireless_core_reset(dev, tmp); diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 77fda148ac468..038baa8869e23 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -607,6 +607,7 @@ struct b43legacy_wl { u8 nr_devs; bool radiotap_enabled; + bool radio_enabled; /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index e5136fb65dddb..c4973c1942bfd 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2689,8 +2689,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Antennas for RX and management frame TX. */ b43legacy_mgmtframe_txantenna(dev, antenna_tx); - if (!!conf->radio_enabled != phy->radio_on) { - if (conf->radio_enabled) { + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { b43legacy_radio_turn_on(dev); b43legacyinfo(dev->wl, "Radio turned on by software\n"); if (!dev->radio_hw_enable) @@ -3441,6 +3441,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; wl->beacon_templates_virgin = 1; + wl->radio_enabled = 1; mutex_lock(&wl->mutex); @@ -3479,6 +3480,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) b43legacy_wireless_core_stop(dev); b43legacy_wireless_core_exit(dev); + wl->radio_enabled = 0; mutex_unlock(&wl->mutex); } @@ -3620,6 +3622,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) have_bphy = 1; dev->phy.gmode = (have_gphy || have_bphy); + dev->phy.radio_on = 1; tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; b43legacy_wireless_core_reset(dev, tmp); -- GitLab From cbfe89c67b58e2bd1b47f6986b3b793f06f3d9b0 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan <vasanth@atheros.com> Date: Wed, 24 Jun 2009 18:58:47 +0530 Subject: [PATCH 0815/1002] ath9k: Fix leak in tx descriptor When we reclaim the tx desc, we always assume that the last desc is a holding desc, which is not true, and skip it. If the tx queue is drained during channel change, internal reset and etc, the last descriptor may not be the holding descriptor and we fail to reclaim them. This results in the following two issues. 1. Tx stuck - We drop all the frames coming from upper layer due to shortage in tx desc. 2. Crash - If we fail to reclaim a tx descriptor, we miss to update the tx BA window with the seq number of the frame associated to that desc, which, at some point, result in the following crash due to an assert failure in ath_tx_addto_baw(). This patch fixes these two issues. kernel BUG at ../drivers/net/wireless/ath/ath9k/xmit.c:180! [155064.304164] invalid opcode: 0000 [#1] SMP Call Trace: [<fbc6d83b>] ? ath9k_tx+0xeb/0x160 [ath9k] [<fbbc9591>] ipv6? __ieee80211_tx+0x41/0x120 [mac80211] [<fbbcb5ae>] ? aes_i586ieee80211_master_start_xmit+0x28e/0x560 [mac80211] [<c037e501>] aes_generic? _spin_lock_irqsave+0x31/0x40 [<c02f347b>] ? dev_hard_start_xmit+0x16b/0x1c0 [<c03058b5>] ? __qdisc_run+0x1b5/0x200 [<fbbcda5a>] ? af_packetieee80211_select_queue+0xa/0x100 [mac80211] [<c02f53b7>] ? i915dev_queue_xmit+0x2e7/0x3f0 [<fbbc9b49>] ? ieee80211_subif_start_xmit+0x369/0x7a0 [mac80211] [<c031bc35>] ? ip_output+0x55/0xb0 [<c02e0188>] ? show_memcpy_count+0x18/0x60 [<c02eb186>] ? __kfree_skb+0x36/0x90 [<c02f2202>] ? binfmt_miscdev_queue_xmit_nit+0xd2/0x110 [<c02f347b>] ? dev_hard_start_xmit+0x16b/0x1c0 [<c03058b5>] ? __qdisc_run+0x1b5/0x200 [<c033bca7>] ? scoarp_create+0x57/0x2a0 [<c02f53b7>] ? bridgedev_queue_xmit+0x2e7/0x3f0 [<c03034a0>] ? eth_header+0x0/0xc0 [<c033b95f>] stp? arp_xmit+0x5f/0x70 [<c033bf4f>] ? arp_send+0x5f/0x70 [<c033c8f5>] bnep? arp_solicit+0x105/0x210 [<c02fa5aa>] ? neigh_timer_handler+0x19a/0x390 [<c013bf88>] ? run_timer_softirq+0x138/0x210 [<c02fa410>] ? ppdevneigh_timer_handler+0x0/0x390 [<c02fa410>] ? neigh_timer_handler+0x0/0x390 Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/ath/ath9k/xmit.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b61a071788a50..4ccf48e396dfd 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } if (bf_next == NULL) { - INIT_LIST_HEAD(&bf_head); + /* + * Make sure the last desc is reclaimed if it + * not a holding desc. + */ + if (!bf_last->bf_stale) + list_move_tail(&bf->list, &bf_head); + else + INIT_LIST_HEAD(&bf_head); } else { ASSERT(!list_empty(bf_q)); list_move_tail(&bf->list, &bf_head); -- GitLab From a7a4e41ed62a6a1fce6eb503c920f615eca27f02 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz <sameo@linux.intel.com> Date: Wed, 24 Jun 2009 16:07:22 +0200 Subject: [PATCH 0816/1002] iwmc3200wifi: add Kconfig help We're missing a Kconfig help for the iwmc3200wifi driver. Signed-off-by: Samuel Ortiz <samuel.ortiz@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/iwmc3200wifi/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 1eccb6df46dd9..030401d367d30 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -4,6 +4,15 @@ config IWM depends on CFG80211 select WIRELESS_EXT select FW_LOADER + help + The Intel Wireless Multicomm 3200 hardware is a combo + card with GPS, Bluetooth, WiMax and 802.11 radios. It + runs over SDIO and is typically found on Moorestown + based platform. This driver takes care of the 802.11 + part, which is a fullmac one. + + If you choose to build it as a module, it'll be called + iwmc3200wifi.ko. config IWM_DEBUG bool "Enable full debugging output in iwmc3200wifi" -- GitLab From 59615b5f9d1323898ca94e88e595b5b04115076a Mon Sep 17 00:00:00 2001 From: Andrey Yurovsky <andrey@cozybit.com> Date: Thu, 25 Jun 2009 16:07:42 -0700 Subject: [PATCH 0817/1002] mac80211: fix allocation in mesh_queue_preq We allocate a PREQ queue node in mesh_queue_preq, however the allocation may cause us to sleep. Use GFP_ATOMIC to prevent this. [ 1869.126498] BUG: scheduling while atomic: ping/1859/0x10000100 [ 1869.127164] Modules linked in: ath5k mac80211 ath [ 1869.128310] Pid: 1859, comm: ping Not tainted 2.6.30-wl #1 [ 1869.128754] Call Trace: [ 1869.129293] [<c1023a2b>] __schedule_bug+0x48/0x4d [ 1869.129866] [<c13b5533>] __schedule+0x77/0x67a [ 1869.130544] [<c1026f2e>] ? release_console_sem+0x17d/0x185 [ 1869.131568] [<c807cf47>] ? mesh_queue_preq+0x2b/0x165 [mac80211] [ 1869.132318] [<c13b5b3e>] schedule+0x8/0x1f [ 1869.132807] [<c1023c12>] __cond_resched+0x16/0x2f [ 1869.133478] [<c13b5bf0>] _cond_resched+0x27/0x32 [ 1869.134191] [<c108a370>] kmem_cache_alloc+0x1c/0xcf [ 1869.134714] [<c10273ae>] ? printk+0x15/0x17 [ 1869.135670] [<c807cf47>] mesh_queue_preq+0x2b/0x165 [mac80211] [ 1869.136731] [<c807d1f8>] mesh_nexthop_lookup+0xee/0x12d [mac80211] [ 1869.138130] [<c807417e>] ieee80211_xmit+0xe6/0x2b2 [mac80211] [ 1869.138935] [<c80be46d>] ? ath5k_hw_setup_rx_desc+0x0/0x66 [ath5k] [ 1869.139831] [<c80c97bc>] ? ath5k_tasklet_rx+0xba/0x506 [ath5k] [ 1869.140863] [<c8075191>] ieee80211_subif_start_xmit+0x6c9/0x6e4 [mac80211] [ 1869.141665] [<c105cf1c>] ? handle_level_irq+0x78/0x9d [ 1869.142390] [<c12e3f93>] dev_hard_start_xmit+0x168/0x1c7 [ 1869.143092] [<c12f1f17>] __qdisc_run+0xe1/0x1b7 [ 1869.143612] [<c12e25ff>] qdisc_run+0x18/0x1a [ 1869.144248] [<c12e62f4>] dev_queue_xmit+0x16a/0x25a [ 1869.144785] [<c13b6dcc>] ? _read_unlock_bh+0xe/0x10 [ 1869.145465] [<c12eacdb>] neigh_resolve_output+0x19c/0x1c7 [ 1869.146182] [<c130e2da>] ? ip_finish_output+0x0/0x51 [ 1869.146697] [<c130e2a0>] ip_finish_output2+0x182/0x1bc [ 1869.147358] [<c130e327>] ip_finish_output+0x4d/0x51 [ 1869.147863] [<c130e9d5>] ip_output+0x80/0x85 [ 1869.148515] [<c130cc49>] dst_output+0x9/0xb [ 1869.149141] [<c130dec6>] ip_local_out+0x17/0x1a [ 1869.149632] [<c130e0bc>] ip_push_pending_frames+0x1f3/0x255 [ 1869.150343] [<c13247ff>] raw_sendmsg+0x5e6/0x667 [ 1869.150883] [<c1033c55>] ? insert_work+0x6a/0x73 [ 1869.151834] [<c8071e00>] ? ieee80211_invoke_rx_handlers+0x17da/0x1ae8 [mac80211] [ 1869.152630] [<c132bd68>] inet_sendmsg+0x3b/0x48 [ 1869.153232] [<c12d7deb>] __sock_sendmsg+0x45/0x4e [ 1869.153740] [<c12d8537>] sock_sendmsg+0xb8/0xce [ 1869.154519] [<c80be46d>] ? ath5k_hw_setup_rx_desc+0x0/0x66 [ath5k] [ 1869.155289] [<c1036b25>] ? autoremove_wake_function+0x0/0x30 [ 1869.155859] [<c115992b>] ? __copy_from_user_ll+0x11/0xce [ 1869.156573] [<c1159d99>] ? copy_from_user+0x31/0x54 [ 1869.157235] [<c12df646>] ? verify_iovec+0x40/0x6e [ 1869.157778] [<c12d869a>] sys_sendmsg+0x14d/0x1a5 [ 1869.158714] [<c8072c40>] ? __ieee80211_rx+0x49e/0x4ee [mac80211] [ 1869.159641] [<c80c83fe>] ? ath5k_rxbuf_setup+0x6d/0x8d [ath5k] [ 1869.160543] [<c80be46d>] ? ath5k_hw_setup_rx_desc+0x0/0x66 [ath5k] [ 1869.161434] [<c80beba4>] ? ath5k_hw_get_rxdp+0xe/0x10 [ath5k] [ 1869.162319] [<c80c97bc>] ? ath5k_tasklet_rx+0xba/0x506 [ath5k] [ 1869.163063] [<c1005627>] ? enable_8259A_irq+0x40/0x43 [ 1869.163594] [<c101edb8>] ? __dequeue_entity+0x23/0x27 [ 1869.164793] [<c100187a>] ? __switch_to+0x2b/0x105 [ 1869.165442] [<c1021d5f>] ? finish_task_switch+0x5b/0x74 [ 1869.166129] [<c12d963a>] sys_socketcall+0x14b/0x17b [ 1869.166612] [<c1002b95>] syscall_call+0x7/0xb Signed-off-by: Andrey Yurovsky <andrey@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/mesh_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 003cb470ac847..f49ef288e2e28 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -637,7 +637,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; - preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); + preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); if (!preq_node) { printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); return; -- GitLab From 76d8b64e536362e16e38ee1c279c965ebfe094cc Mon Sep 17 00:00:00 2001 From: Johannes Berg <johannes@sipsolutions.net> Date: Mon, 29 Jun 2009 10:53:53 +0200 Subject: [PATCH 0818/1002] hp-wmi: fix rfkill bug Fix the third (I think) polarity error I accidentally introduced in the rfkill rewrite to make wireless work again on (certain?) HP laptops. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Tested-by: Maciej Rutecki <maciej.rutecki@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/platform/x86/hp-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 4ac2311c00afe..ca508564a1814 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void) static int hp_wmi_set_block(void *data, bool blocked) { unsigned long b = (unsigned long) data; - int query = BIT(b + 8) | ((!!blocked) << b); + int query = BIT(b + 8) | ((!blocked) << b); return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); } -- GitLab From 2dce4c2b5f0b43bd25bf9ea6ded06b7f8a54c91f Mon Sep 17 00:00:00 2001 From: Johannes Berg <johannes@sipsolutions.net> Date: Thu, 2 Jul 2009 15:46:41 +0200 Subject: [PATCH 0819/1002] cfg80211: fix refcount leak The code in cfg80211's cfg80211_bss_update erroneously grabs a reference to the BSS, which means that it will never be freed. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: stable@kernel.org [2.6.29, 2.6.30] Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/wireless/scan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e95b638b919f5..f8e71b300001e 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -366,7 +366,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, found = rb_find_bss(dev, res); if (found) { - kref_get(&found->ref); found->pub.beacon_interval = res->pub.beacon_interval; found->pub.tsf = res->pub.tsf; found->pub.signal = res->pub.signal; -- GitLab From 3938b45c1c75e53d45eb65ac253f12e86239c9ba Mon Sep 17 00:00:00 2001 From: Luciano Coelho <luciano.coelho@nokia.com> Date: Fri, 3 Jul 2009 08:25:08 +0300 Subject: [PATCH 0820/1002] mac80211: minstrel: avoid accessing negative indices in rix_to_ndx() If rix is not found in mi->r[], i will become -1 after the loop. This value is eventually used to access arrays, so we were accessing arrays with a negative index, which is obviously not what we want to do. This patch fixes this potential problem. Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/rc80211_minstrel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b218b98fba7fb..37771abd8f5a5 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -66,7 +66,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) for (i = rix; i >= 0; i--) if (mi->r[i].rix == rix) break; - WARN_ON(mi->r[i].rix != rix); + WARN_ON(i < 0); return i; } @@ -181,6 +181,9 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, break; ndx = rix_to_ndx(mi, ar[i].idx); + if (ndx < 0) + continue; + mi->r[ndx].attempts += ar[i].count; if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) -- GitLab From 22bd50c5b9aaf46476cade52c4ae9afa21c44e15 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang <zhenyuw@linux.intel.com> Date: Mon, 6 Jul 2009 17:27:52 +0800 Subject: [PATCH 0821/1002] drm/i915: Don't update display FIFO watermark on IGDNG Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 47ecb617e519b..9aa3263c56dcf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -892,7 +892,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) /* dsparb controlled by hw only */ -#define DSPARB_HWCONTROL(dev) (IS_G4X(dev)) +#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) -- GitLab From 8e4d36b993898b344f9176147f1dfeca583f81fd Mon Sep 17 00:00:00 2001 From: "ling.ma@intel.com" <ling.ma@intel.com> Date: Tue, 30 Jun 2009 11:35:34 +0800 Subject: [PATCH 0822/1002] drm/i915: crt fetch EDID by DVI-I converter on G4x platform Usually crt mainly get modes via GPIOA ports. However on G4X platform we need to probe possible ports for DVI-I, which could be wired to GPIOD, then fetch our desired EDID, i.e on DG45ID platform we successfully fetch EDID by GPIOD port. It fixed freedesktop.org bug #21084 Signed-off-by: Ma Ling <ling.ma@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_crt.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6de97fc66029e..af26028c2514d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -428,8 +428,34 @@ static void intel_crt_destroy(struct drm_connector *connector) static int intel_crt_get_modes(struct drm_connector *connector) { + int ret; struct intel_output *intel_output = to_intel_output(connector); - return intel_ddc_get_modes(intel_output); + struct intel_i2c_chan *ddcbus; + struct drm_device *dev = connector->dev; + + + ret = intel_ddc_get_modes(intel_output); + if (ret || !IS_G4X(dev)) + goto end; + + ddcbus = intel_output->ddc_bus; + /* Try to probe digital port for output in DVI-I -> VGA mode. */ + intel_output->ddc_bus = + intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); + + if (!intel_output->ddc_bus) { + intel_output->ddc_bus = ddcbus; + dev_printk(KERN_ERR, &connector->dev->pdev->dev, + "DDC bus registration failed for CRTDDC_D.\n"); + goto end; + } + /* Try to get modes by GPIOD port */ + ret = intel_ddc_get_modes(intel_output); + intel_i2c_destroy(ddcbus); + +end: + return ret; + } static int intel_crt_set_property(struct drm_connector *connector, -- GitLab From febc7694a55277b70cd662de05ed8a957685959c Mon Sep 17 00:00:00 2001 From: "ling.ma@intel.com" <ling.ma@intel.com> Date: Thu, 25 Jun 2009 11:55:57 +0800 Subject: [PATCH 0823/1002] drm/i915: Disable VGA output when doing DRM_MODE_DPMS_OFF. Signed-off-by: Ma Ling <ling.ma@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_crt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index af26028c2514d..954b8599fc761 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -46,7 +46,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) temp = I915_READ(reg); temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); - temp |= ADPA_DAC_ENABLE; + temp &= ~ADPA_DAC_ENABLE; switch(mode) { case DRM_MODE_DPMS_ON: -- GitLab From b5323599af68caa2da08b7041400b62049afb91e Mon Sep 17 00:00:00 2001 From: Ben Gamari <bgamari.foss@gmail.com> Date: Wed, 1 Jul 2009 15:01:34 -0400 Subject: [PATCH 0824/1002] drm/i915: Remove gtt_bound from drm_i915_gem_object This wasn't even used as far as I could tell and will only confuse people (like me). Signed-off-by: Ben Gamari <bgamari.foss@gmail.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_drv.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9aa3263c56dcf..9d6889799d01e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -489,9 +489,6 @@ struct drm_i915_gem_object { */ int fence_reg; - /** Boolean whether this object has a valid gtt offset. */ - int gtt_bound; - /** How many users have pinned this object in GTT space */ int pin_count; -- GitLab From a01c75b338d7c743a8982011f01a4714ad2956de Mon Sep 17 00:00:00 2001 From: Ben Gamari <bgamari.foss@gmail.com> Date: Wed, 1 Jul 2009 15:01:35 -0400 Subject: [PATCH 0825/1002] drm/i915: Add gtt_offset to gem object list debugfs output This is quite useful for verifying that objects are actually mapped when they need to be. Signed-off-by: Ben Gamari <bgamari.foss@gmail.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index cacae945338b8..a61d656cfd21d 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -104,7 +104,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) if (obj->name) seq_printf(m, " (name: %d)", obj->name); if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - seq_printf(m, " (fence: %d)\n", obj_priv->fence_reg); + seq_printf(m, " (fence: %d)", obj_priv->fence_reg); + if (obj_priv->gtt_space != NULL) + seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset); + seq_printf(m, "\n"); } -- GitLab From a17458fc9d9edc98b7c5865cdc42681cf9059f1c Mon Sep 17 00:00:00 2001 From: Ben Gamari <bgamari.foss@gmail.com> Date: Wed, 1 Jul 2009 15:01:36 -0400 Subject: [PATCH 0826/1002] drm/i915: Move lock to more reasonable location Make this consistent with the unlock statement. Also fix a minor typo in debugfs formatting Signed-off-by: Ben Gamari <bgamari.foss@gmail.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c index a61d656cfd21d..9a44bfcb81394 100644 --- a/drivers/gpu/drm/i915/i915_gem_debugfs.c +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c @@ -75,11 +75,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) case ACTIVE_LIST: seq_printf(m, "Active:\n"); lock = &dev_priv->mm.active_list_lock; - spin_lock(lock); head = &dev_priv->mm.active_list; break; case INACTIVE_LIST: - seq_printf(m, "Inctive:\n"); + seq_printf(m, "Inactive:\n"); head = &dev_priv->mm.inactive_list; break; case FLUSHING_LIST: @@ -91,6 +90,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) return 0; } + if (lock) + spin_lock(lock); list_for_each_entry(obj_priv, head, list) { struct drm_gem_object *obj = obj_priv->obj; -- GitLab From 551a232c87b7781712c57c31f3e0851303d9f591 Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:50 +0000 Subject: [PATCH 0827/1002] powerpc/pseries: Use pr_devel() in pseries LPAR HPTE routines pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. In particular, pSeries_lpar_hpte_insert() goes from 185 instructions to 77 instructions as a result of this patch. Luckily that code isn't called very often ... With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 7284 1552 296 9132 23ac platforms/pseries/lpar.o size after: text data bss dec hex filename 5806 1096 296 7198 1c1e platforms/pseries/lpar.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/pseries/lpar.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e3139fa5e556e..903eb9eec6874 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -286,7 +286,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long hpte_v, hpte_r; if (!(vflags & HPTE_V_BOLTED)) - pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " + pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " "rflags=%lx, vflags=%lx, psize=%d)\n", hpte_group, va, pa, rflags, vflags, psize); @@ -294,7 +294,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, hpte_r = hpte_encode_r(pa, psize) | rflags; if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); + pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); /* Now fill in the actual HPTE */ /* Set CEC cookie to 0 */ @@ -311,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); if (unlikely(lpar_rc == H_PTEG_FULL)) { if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" full\n"); + pr_devel(" full\n"); return -1; } @@ -322,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, */ if (unlikely(lpar_rc != H_SUCCESS)) { if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" lpar err %lu\n", lpar_rc); + pr_devel(" lpar err %lu\n", lpar_rc); return -2; } if (!(vflags & HPTE_V_BOLTED)) - pr_debug(" -> slot: %lu\n", slot & 7); + pr_devel(" -> slot: %lu\n", slot & 7); /* Because of iSeries, we have to pass down the secondary * bucket bit here as well @@ -418,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, want_v = hpte_encode_avpn(va, psize, ssize); - pr_debug(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", + pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", want_v, slot, flags, psize); lpar_rc = plpar_pte_protect(flags, slot, want_v); if (lpar_rc == H_NOT_FOUND) { - pr_debug("not found !\n"); + pr_devel("not found !\n"); return -1; } - pr_debug("ok\n"); + pr_devel("ok\n"); BUG_ON(lpar_rc != H_SUCCESS); @@ -503,7 +503,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, unsigned long lpar_rc; unsigned long dummy1, dummy2; - pr_debug(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", + pr_devel(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", slot, va, psize, local); want_v = hpte_encode_avpn(va, psize, ssize); -- GitLab From d258e64ef595792d6f749518354b69583e9a97f4 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 06:26:10 +0000 Subject: [PATCH 0828/1002] powerpc: Remove unnecessary semicolons Signed-off-by: Joe Perches <joe@perches.com> Acked-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/mm/tlb_hash64.c | 2 +- arch/powerpc/oprofile/cell/vma_map.c | 2 +- arch/powerpc/platforms/powermac/cpufreq_64.c | 2 +- arch/powerpc/platforms/powermac/pic.c | 2 +- arch/powerpc/platforms/ps3/system-bus.c | 1 - arch/powerpc/sysdev/fsl_rio.c | 2 +- arch/powerpc/sysdev/ppc4xx_pci.c | 4 ++-- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 1be1b5e597962..937eb90677d9e 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -72,7 +72,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, */ if (huge) { #ifdef CONFIG_HUGETLB_PAGE - psize = get_slice_psize(mm, addr);; + psize = get_slice_psize(mm, addr); #else BUG(); psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */ diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c index 258fa4411e9e4..c591339daf58a 100644 --- a/arch/powerpc/oprofile/cell/vma_map.c +++ b/arch/powerpc/oprofile/cell/vma_map.c @@ -185,7 +185,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu, goto fail; if (shdr_str.sh_type != SHT_STRTAB) - goto fail;; + goto fail; for (j = 0; j < shdr.sh_size / sizeof (sym); j++) { if (copy_from_user(&sym, spu_elf_start + diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 22ecfbe7183de..708c751333770 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -251,7 +251,7 @@ static void g5_pfunc_switch_volt(int speed_mode) static struct pmf_function *pfunc_cpu_setfreq_high; static struct pmf_function *pfunc_cpu_setfreq_low; static struct pmf_function *pfunc_cpu_getfreq; -static struct pmf_function *pfunc_slewing_done;; +static struct pmf_function *pfunc_slewing_done; static int g5_pfunc_switch_freq(int speed_mode) { diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index dce736349107b..d212006a5b3c0 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -609,7 +609,7 @@ static int pmacpic_find_viaint(void) np = of_find_node_by_name(NULL, "via-pmu"); if (np == NULL) goto not_found; - viaint = irq_of_parse_and_map(np, 0);; + viaint = irq_of_parse_and_map(np, 0); not_found: #endif /* CONFIG_ADB_PMU */ diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 9fead0faf38bb..3f763c5284acc 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -284,7 +284,6 @@ static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) int result; dump_mmio_region(r); -; result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, r->lpar_addr); diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 39db9d1155d27..cbb3bed75d3c0 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -965,7 +965,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr) break; default: str = "Unknown"; - break;; + break; } dev_info(dev, "Hardware port width: %s\n", str); diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index daefc93ddffec..6ff9d71b4c0d8 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1531,7 +1531,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, */ /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(ep_size));; + sa = (0xffffffffffffffffull << ilog2(ep_size)); /* Setup BAR0 */ out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); @@ -1550,7 +1550,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr)); } else { /* Calculate window size */ - sa = (0xffffffffffffffffull << ilog2(size));; + sa = (0xffffffffffffffffull << ilog2(size)); if (res->flags & IORESOURCE_PREFETCH) sa |= 0x8; -- GitLab From b69e9e931d2c6116921fdb260684e0546285c3c8 Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:53 +0000 Subject: [PATCH 0829/1002] powerpc/pseries: Use pr_devel() in xics.c pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 7720 5488 296 13504 34c0 platforms/pseries/xics.o size after: text data bss dec hex filename 7535 5456 296 13287 33e7 platforms/pseries/xics.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/pseries/xics.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index be3581a8c294c..419f8a637ffe5 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -190,10 +190,10 @@ static void xics_unmask_irq(unsigned int virq) int call_status; int server; - pr_debug("xics: unmask virq %d\n", virq); + pr_devel("xics: unmask virq %d\n", virq); irq = (unsigned int)irq_map[virq].hwirq; - pr_debug(" -> map to hwirq 0x%x\n", irq); + pr_devel(" -> map to hwirq 0x%x\n", irq); if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) return; @@ -252,7 +252,7 @@ static void xics_mask_irq(unsigned int virq) { unsigned int irq; - pr_debug("xics: mask virq %d\n", virq); + pr_devel("xics: mask virq %d\n", virq); irq = (unsigned int)irq_map[virq].hwirq; if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) @@ -414,7 +414,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node) static int xics_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { - pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw); + pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); /* Insert the interrupt mapping into the radix tree for fast lookup */ irq_radix_revmap_insert(xics_host, virq, hw); -- GitLab From a1ac38ab98e8a79ce225347b725f3b9751c70f1e Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:54 +0000 Subject: [PATCH 0830/1002] powerpc: Use pr_devel() in arch/powerpc/mm/mmu_context_nohash.c pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 1508 48 28 1584 630 powerpc/mm/mmu_context_nohash.o size after: text data bss dec hex filename 1088 0 28 1116 45c powerpc/mm/mmu_context_nohash.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/mm/mmu_context_nohash.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index 8343986809c03..92a197117d5b8 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c @@ -89,7 +89,7 @@ static unsigned int steal_context_smp(unsigned int id) id = first_context; continue; } - pr_debug("[%d] steal context %d from mm @%p\n", + pr_devel("[%d] steal context %d from mm @%p\n", smp_processor_id(), id, mm); /* Mark this mm has having no context anymore */ @@ -126,7 +126,7 @@ static unsigned int steal_context_up(unsigned int id) /* Pick up the victim mm */ mm = context_mm[id]; - pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm); + pr_devel("[%d] steal context %d from mm @%p\n", cpu, id, mm); /* Flush the TLB for that context */ local_flush_tlb_mm(mm); @@ -180,7 +180,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) spin_lock(&context_lock); #ifndef DEBUG_STEAL_ONLY - pr_debug("[%d] activating context for mm @%p, active=%d, id=%d\n", + pr_devel("[%d] activating context for mm @%p, active=%d, id=%d\n", cpu, next, next->context.active, next->context.id); #endif @@ -189,7 +189,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) next->context.active++; if (prev) { #ifndef DEBUG_STEAL_ONLY - pr_debug(" old context %p active was: %d\n", + pr_devel(" old context %p active was: %d\n", prev, prev->context.active); #endif WARN_ON(prev->context.active < 1); @@ -236,7 +236,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) next->context.id = id; #ifndef DEBUG_STEAL_ONLY - pr_debug("[%d] picked up new id %d, nrf is now %d\n", + pr_devel("[%d] picked up new id %d, nrf is now %d\n", cpu, id, nr_free_contexts); #endif @@ -247,7 +247,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next) * local TLB for it and unmark it before we use it */ if (test_bit(id, stale_map[cpu])) { - pr_debug("[%d] flushing stale context %d for mm @%p !\n", + pr_devel("[%d] flushing stale context %d for mm @%p !\n", cpu, id, next); local_flush_tlb_mm(next); @@ -314,13 +314,13 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - pr_debug("MMU: Allocating stale context map for CPU %d\n", cpu); + pr_devel("MMU: Allocating stale context map for CPU %d\n", cpu); stale_map[cpu] = kzalloc(CTX_MAP_SIZE, GFP_KERNEL); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: case CPU_DEAD_FROZEN: - pr_debug("MMU: Freeing stale context map for CPU %d\n", cpu); + pr_devel("MMU: Freeing stale context map for CPU %d\n", cpu); kfree(stale_map[cpu]); stale_map[cpu] = NULL; break; -- GitLab From 3665ee36fac936b2ad0ab170d101a3e2c8eb3fd2 Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Sat, 20 Jun 2009 13:37:00 +0000 Subject: [PATCH 0831/1002] powerpc/perf_counter: Remove duplicated #include Remove duplicated #include('s) in arch/powerpc/kernel/mpc7450-pmu.c arch/powerpc/kernel/ppc970-pmu.c Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/kernel/mpc7450-pmu.c | 1 - arch/powerpc/kernel/ppc970-pmu.c | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c index 75ff47fed7bfc..c244133c67a67 100644 --- a/arch/powerpc/kernel/mpc7450-pmu.c +++ b/arch/powerpc/kernel/mpc7450-pmu.c @@ -10,7 +10,6 @@ */ #include <linux/string.h> #include <linux/perf_counter.h> -#include <linux/string.h> #include <asm/reg.h> #include <asm/cputable.h> diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index 6637c87fe70eb..833097ac45dc4 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c @@ -10,7 +10,6 @@ */ #include <linux/string.h> #include <linux/perf_counter.h> -#include <linux/string.h> #include <asm/reg.h> #include <asm/cputable.h> -- GitLab From 651e2dd2a1c47bb078d446f123a9ae950ba7a1f0 Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:51 +0000 Subject: [PATCH 0832/1002] powerpc: Cleanup & use pr_devel() in arch/powerpc/mm/slb.c pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 3261 416 4 3681 e61 arch/powerpc/mm/slb.o size after: text data bss dec hex filename 2861 248 4 3113 c29 arch/powerpc/mm/slb.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/mm/slb.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 3b52c80e5e338..5b7038f248b60 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -14,8 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#undef DEBUG - #include <asm/pgtable.h> #include <asm/mmu.h> #include <asm/mmu_context.h> @@ -27,11 +25,6 @@ #include <linux/compiler.h> #include <asm/udbg.h> -#ifdef DEBUG -#define DBG(fmt...) printk(fmt) -#else -#define DBG pr_debug -#endif extern void slb_allocate_realmode(unsigned long ea); extern void slb_allocate_user(unsigned long ea); @@ -285,13 +278,13 @@ void slb_initialize(void) patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size); - DBG("SLB: linear LLP = %04lx\n", linear_llp); - DBG("SLB: io LLP = %04lx\n", io_llp); + pr_devel("SLB: linear LLP = %04lx\n", linear_llp); + pr_devel("SLB: io LLP = %04lx\n", io_llp); #ifdef CONFIG_SPARSEMEM_VMEMMAP patch_slb_encoding(slb_miss_kernel_load_vmemmap, SLB_VSID_KERNEL | vmemmap_llp); - DBG("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); + pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); #endif } -- GitLab From 29e5fa59e5ebe06d6bd7e04e7752a47ead23f89e Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:51 +0000 Subject: [PATCH 0833/1002] powerpc: Use pr_devel() in arch/powerpc/mm/gup.c pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 3252 384 0 3636 e34 arch/powerpc/mm/gup.o size after: text data bss dec hex filename 2576 96 0 2672 a70 arch/powerpc/mm/gup.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/mm/gup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c index bc400c78c97fb..bc122a120bf00 100644 --- a/arch/powerpc/mm/gup.c +++ b/arch/powerpc/mm/gup.c @@ -159,7 +159,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, int psize; #endif - pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); + pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); start &= PAGE_MASK; addr = start; @@ -170,7 +170,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, start, len))) goto slow_irqon; - pr_debug(" aligned: %lx .. %lx\n", start, end); + pr_devel(" aligned: %lx .. %lx\n", start, end); #ifdef CONFIG_HUGETLB_PAGE /* We bail out on slice boundary crossing when hugetlb is @@ -234,7 +234,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, do { VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift); ptep = huge_pte_offset(mm, a); - pr_debug(" %016lx: huge ptep %p\n", a, ptep); + pr_devel(" %016lx: huge ptep %p\n", a, ptep); if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages, &nr)) goto slow; @@ -249,7 +249,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, #ifdef CONFIG_PPC64 VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift); #endif - pr_debug(" %016lx: normal pgd %p\n", addr, + pr_devel(" %016lx: normal pgd %p\n", addr, (void *)pgd_val(pgd)); next = pgd_addr_end(addr, end); if (pgd_none(pgd)) @@ -269,7 +269,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, slow: local_irq_enable(); slow_irqon: - pr_debug(" slow path ! nr = %d\n", nr); + pr_devel(" slow path ! nr = %d\n", nr); /* Try to get the remaining pages with get_user_pages */ start += nr << PAGE_SHIFT; -- GitLab From 33875f03307452650309a7d071678b2ca5f2fc26 Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:53 +0000 Subject: [PATCH 0834/1002] powerpc/cell: Use pr_devel() in axon_msi.c pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 7083 1616 0 8699 21fb arch/powerpc/../axon_msi.o size after: text data bss dec hex filename 5772 1208 0 6980 1b44 arch/powerpc/../axon_msi.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/cell/axon_msi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index c71498dbf2117..aca5741ddc677 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -85,7 +85,7 @@ static inline void axon_msi_debug_setup(struct device_node *dn, static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) { - pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); + pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); dcr_write(msic->dcr_host, dcr_n, val); } @@ -98,7 +98,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) int retry = 0; write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG); - pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); + pr_devel("axon_msi: original write_offset 0x%x\n", write_offset); /* write_offset doesn't wrap properly, so we have to mask it */ write_offset &= MSIC_FIFO_SIZE_MASK; @@ -108,7 +108,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) msi = le32_to_cpu(msic->fifo_virt[idx]); msi &= 0xFFFF; - pr_debug("axon_msi: woff %x roff %x msi %x\n", + pr_devel("axon_msi: woff %x roff %x msi %x\n", write_offset, msic->read_offset, msi); if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) { @@ -123,12 +123,12 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) */ udelay(1); retry++; - pr_debug("axon_msi: invalid irq 0x%x!\n", msi); + pr_devel("axon_msi: invalid irq 0x%x!\n", msi); continue; } if (retry) { - pr_debug("axon_msi: late irq 0x%x, retry %d\n", + pr_devel("axon_msi: late irq 0x%x, retry %d\n", msi, retry); retry = 0; } @@ -332,7 +332,7 @@ static int axon_msi_shutdown(struct of_device *device) struct axon_msic *msic = dev_get_drvdata(&device->dev); u32 tmp; - pr_debug("axon_msi: disabling %s\n", + pr_devel("axon_msi: disabling %s\n", msic->irq_host->of_node->full_name); tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; @@ -349,7 +349,7 @@ static int axon_msi_probe(struct of_device *device, unsigned int virq; int dcr_base, dcr_len; - pr_debug("axon_msi: setting up dn %s\n", dn->full_name); + pr_devel("axon_msi: setting up dn %s\n", dn->full_name); msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL); if (!msic) { @@ -403,7 +403,7 @@ static int axon_msi_probe(struct of_device *device, set_irq_data(virq, msic); set_irq_chained_handler(virq, axon_msi_cascade); - pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); + pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq); /* Enable the MSIC hardware */ msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32); @@ -484,13 +484,13 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) addr = of_translate_address(dn, of_get_property(dn, "reg", NULL)); if (addr == OF_BAD_ADDR) { - pr_debug("axon_msi: couldn't translate reg property\n"); + pr_devel("axon_msi: couldn't translate reg property\n"); return; } msic->trigger = ioremap(addr, 0x4); if (!msic->trigger) { - pr_debug("axon_msi: ioremap failed\n"); + pr_devel("axon_msi: ioremap failed\n"); return; } @@ -498,7 +498,7 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) if (!debugfs_create_file(name, 0600, powerpc_debugfs_root, msic, &fops_msic)) { - pr_debug("axon_msi: debugfs_create_file failed!\n"); + pr_devel("axon_msi: debugfs_create_file failed!\n"); return; } } -- GitLab From 30c5af435b2e3e5700b0e4a53ac37a39b3b3516e Mon Sep 17 00:00:00 2001 From: Michael Ellerman <michael@ellerman.id.au> Date: Wed, 17 Jun 2009 18:13:52 +0000 Subject: [PATCH 0835/1002] powerpc: Use pr_devel() in do_dcache_icache_coherency() pr_debug() can now result in code being generated even when DEBUG is not defined. That's not really desirable in some places. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 2036 368 8 2412 96c arch/powerpc/mm/pgtable.o size after: text data bss dec hex filename 1677 248 8 1933 78d arch/powerpc/mm/pgtable.o Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/mm/pgtable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index ae1d67cc090cf..627767d6169bd 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -129,12 +129,12 @@ static pte_t do_dcache_icache_coherency(pte_t pte) page = pfn_to_page(pfn); if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { - pr_debug("do_dcache_icache_coherency... flushing\n"); + pr_devel("do_dcache_icache_coherency... flushing\n"); flush_dcache_icache_page(page); set_bit(PG_arch_1, &page->flags); } else - pr_debug("do_dcache_icache_coherency... already clean\n"); + pr_devel("do_dcache_icache_coherency... already clean\n"); return __pte(pte_val(pte) | _PAGE_HWEXEC); } -- GitLab From ad9064d5e22a6a24f828dad63c4775c4d7280bd4 Mon Sep 17 00:00:00 2001 From: Grant Likely <grant.likely@secretlab.ca> Date: Mon, 29 Jun 2009 13:40:51 +0000 Subject: [PATCH 0836/1002] powerpc: Fix spin_event_timeout() to be robust over context switches Current implementation of spin_event_timeout can be interrupted by an IRQ or context switch after testing the condition, but before checking the timeout. This can cause the loop to report a timeout when the condition actually became true in the middle. This patch adds one final check of the condition upon exit of the loop if the last test of the condition was still false. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Timur Tabi <timur@freescale.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/include/asm/delay.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/include/asm/delay.h b/arch/powerpc/include/asm/delay.h index 1e2eb41fa0577..52e4d54da2a98 100644 --- a/arch/powerpc/include/asm/delay.h +++ b/arch/powerpc/include/asm/delay.h @@ -63,6 +63,8 @@ extern void udelay(unsigned long usecs); udelay(delay); \ else \ cpu_relax(); \ + if (!__ret) \ + __ret = (condition); \ __ret; \ }) -- GitLab From ea96025a26ab8949adab1a8e81419202f92f3f7f Mon Sep 17 00:00:00 2001 From: Anton Vorontsov <avorontsov@ru.mvista.com> Date: Wed, 1 Jul 2009 10:59:57 +0000 Subject: [PATCH 0837/1002] powerpc: Don't use alloc_bootmem() in init_IRQ() path This patch fixes various badnesses like this for all interrupt controllers: ------------[ cut here ]------------ Badness at c04db9dc [verbose debug info unavailable] NIP: c04db9dc LR: c04db9ac CTR: 00000000 REGS: c053de30 TRAP: 0700 Not tainted (2.6.31-rc1-00432-ge69b2b5-dirty) MSR: 00021000 <ME,CE> CR: 22020084 XER: 00000000 TASK = c0500480[0] 'swapper' THREAD: c053c000 GPR00: 00000001 c053dee0 c0500480 00000000 00000050 00000020 3fffffff 00000000 GPR08: 00000001 c0540000 e0080080 00000000 22000084 64183600 3ff8f800 00000000 GPR16: 841b0240 449a0303 00000000 00000000 00000000 00000000 00000000 c04f5bf4 GPR24: 00000000 00000000 00000000 00000050 00000020 00000000 3fffffff 00000050 NIP [c04db9dc] alloc_arch_preferred_bootmem+0x48/0x74 LR [c04db9ac] alloc_arch_preferred_bootmem+0x18/0x74 Call Trace: [c053dee0] [c000a5a4] __of_address_to_resource+0x44/0xd0 (unreliable) [c053def0] [c04dba58] ___alloc_bootmem_nopanic+0x50/0x108 [c053df20] [c04dbb28] ___alloc_bootmem+0x18/0x50 [c053df30] [c04d5de0] qe_ic_init+0x5c/0x1b0 [c053df70] [c04d77b0] mpc85xx_mds_pic_init+0xb8/0x10c [c053dfb0] [c04cf374] init_IRQ+0x28/0x3c p.s. commit 85355bb272db31a3f2dd99d547eef794805e1319 ("powerpc: Fix mpic alloc warning") missed some alloc_bootmem() instances, this is now fixed. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Acked-by: Timur Tabi <timur@freescale.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | 2 +- arch/powerpc/sysdev/ipic.c | 4 +--- arch/powerpc/sysdev/mpic.c | 9 ++++----- arch/powerpc/sysdev/qe_lib/qe_ic.c | 4 +--- arch/powerpc/sysdev/uic.c | 3 +-- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index ddf0bdc0fc8ba..7ee979f323d18 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c @@ -147,7 +147,7 @@ int __init pq2ads_pci_init_irq(void) goto out; } - priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic)); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { of_node_put(np); ret = -ENOMEM; diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index a86d3ce01ead9..69e2630c90624 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -728,12 +728,10 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) if (ret) return NULL; - ipic = alloc_bootmem(sizeof(struct ipic)); + ipic = kzalloc(sizeof(*ipic), GFP_KERNEL); if (ipic == NULL) return NULL; - memset(ipic, 0, sizeof(struct ipic)); - ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, NR_IPIC_INTS, &ipic_host_ops, 0); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d46de1f0f3eed..3981ae4cb58e7 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -508,9 +508,8 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n"); /* Allocate fixups array */ - mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup)); + mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL); BUG_ON(mpic->fixups == NULL); - memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup)); /* Init spinlock */ spin_lock_init(&mpic->fixup_lock); @@ -1109,9 +1108,8 @@ struct mpic * __init mpic_alloc(struct device_node *node, psize /= 4; bits = intvec_top + 1; mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); - mpic->protected = alloc_bootmem(mapsize); + mpic->protected = kzalloc(mapsize, GFP_KERNEL); BUG_ON(mpic->protected == NULL); - memset(mpic->protected, 0, mapsize); for (i = 0; i < psize; i++) { if (psrc[i] > intvec_top) continue; @@ -1353,7 +1351,8 @@ void __init mpic_init(struct mpic *mpic) #ifdef CONFIG_PM /* allocate memory to save mpic state */ - mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save)); + mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data), + GFP_KERNEL); BUG_ON(mpic->save_data == NULL); #endif } diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index 63cdf9887f367..074905c3ee5a9 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -333,12 +333,10 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags, if (ret) return; - qe_ic = alloc_bootmem(sizeof(struct qe_ic)); + qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL); if (qe_ic == NULL) return; - memset(qe_ic, 0, sizeof(struct qe_ic)); - qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, NR_QE_IC_INTS, &qe_ic_host_ops, 0); if (qe_ic->irqhost == NULL) diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index d35405c594348..466ce9ace1270 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -258,11 +258,10 @@ static struct uic * __init uic_init_one(struct device_node *node) BUG_ON(! of_device_is_compatible(node, "ibm,uic")); - uic = alloc_bootmem(sizeof(*uic)); + uic = kzalloc(sizeof(*uic), GFP_KERNEL); if (! uic) return NULL; /* FIXME: panic? */ - memset(uic, 0, sizeof(*uic)); spin_lock_init(&uic->lock); indexp = of_get_property(node, "cell-index", &len); if (!indexp || (len != sizeof(u32))) { -- GitLab From 1c55d521f4e58be55735d7ac47e8197d6791fa9a Mon Sep 17 00:00:00 2001 From: Takashi Iwai <tiwai@suse.de> Date: Wed, 8 Jul 2009 07:45:46 +0200 Subject: [PATCH 0838/1002] ALSA: hda - Check widget types while parsing capture source in patch_via.c Check the widget type and don't take invalid widgets while parsing the capture source in patch_via.c. Also, fixed some compile warnings introduced in the previous commit. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_via.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 38db45964228a..9008b4b013aa7 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -392,7 +392,6 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int vendor_id = codec->vendor_id; if (!spec->mux_nids[adc_idx]) return -EINVAL; @@ -1340,6 +1339,10 @@ static int get_mux_nids(struct hda_codec *codec) for (i = 0; i < spec->num_adc_nids; i++) { nid = spec->adc_nids[i]; while (nid) { + type = (get_wcaps(codec, nid) & AC_WCAP_TYPE) + >> AC_WCAP_TYPE_SHIFT; + if (type == AC_WID_PIN) + break; n = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn)); if (n <= 0) @@ -1351,6 +1354,7 @@ static int get_mux_nids(struct hda_codec *codec) nid = conn[0]; } } + return 0; } static int patch_vt1708(struct hda_codec *codec) -- GitLab From ddaa43433dd77535e4e132787f199f58ce224f44 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Date: Tue, 7 Jul 2009 22:10:02 -0700 Subject: [PATCH 0839/1002] Input: mark serio and i8042 as suspended when hibernating too Serio ports are not being restarted any longer because resume operations after hibernate do nothing, since the device has not been marked as suspended. This happens because suspend is only considering the SUSPEND event but not the FREEZE event. Note that this driver has still to migrate to dev_pm_ops, but this fixes this particular bug now. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/serio/i8042.c | 7 ++++--- drivers/input/serio/serio.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f919bf57293c9..582245c497ebf 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -934,10 +934,11 @@ static bool i8042_suspended; static int i8042_suspend(struct platform_device *dev, pm_message_t state) { - if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { + if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) i8042_controller_reset(); - i8042_suspended = true; - } + + i8042_suspended = state.event == PM_EVENT_SUSPEND || + state.event == PM_EVENT_FREEZE; return 0; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index fb17573f8f2d9..d66f4944f2a0e 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state) { struct serio *serio = to_serio_port(dev); - if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { + if (!serio->suspended && state.event == PM_EVENT_SUSPEND) serio_cleanup(serio); - serio->suspended = true; - } + + serio->suspended = state.event == PM_EVENT_SUSPEND || + state.event == PM_EVENT_FREEZE; return 0; } -- GitLab From eeafa5ef6de5acf678624a21f7dba7d43ba73845 Mon Sep 17 00:00:00 2001 From: Saeed Bishara <saeed@marvell.com> Date: Tue, 7 Jul 2009 22:11:52 -0700 Subject: [PATCH 0840/1002] Input: gpio_mouse - use standard driver registration method This patch is needed when the gpio's became available only at late stages, for example, when using i2c gpio expander. Signed-off-by: Saeed Bishara <saeed@marvell.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/mouse/gpio_mouse.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 5e5eb88d8d1e0..7b6ce178f1b67 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) input_sync(input); } -static int __init gpio_mouse_probe(struct platform_device *pdev) +static int __devinit gpio_mouse_probe(struct platform_device *pdev) { struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; struct input_polled_dev *input_poll; @@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) return 0; } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:gpio_mouse"); - static struct platform_driver gpio_mouse_device_driver = { + .probe = gpio_mouse_probe, .remove = __devexit_p(gpio_mouse_remove), .driver = { .name = "gpio_mouse", @@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = { static int __init gpio_mouse_init(void) { - return platform_driver_probe(&gpio_mouse_device_driver, - gpio_mouse_probe); + return platform_driver_register(&gpio_mouse_device_driver); } module_init(gpio_mouse_init); @@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit); MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ + -- GitLab From dc4c2e6bde77735071dbef7aca6bd6c0116102b3 Mon Sep 17 00:00:00 2001 From: Andiry Brienza <andiry.xu@amd.com> Date: Wed, 8 Jul 2009 13:55:31 +0800 Subject: [PATCH 0841/1002] ALSA: hda - Disable AMD SB600 64bit address support only HDA driver disabled HD audio 64bit address support for all AMD SB600/SB700/SB800 platforms with commit 09240cf429505891d6123ce14a29f58f2a60121e due to one SB600 issue reported by community, but we do not see the similar issue on SB700/SB800 platforms. This patch is to refine the workaround for SB600 only. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_intel.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 16e09d7405729..77c1b840ca8b0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2333,9 +2333,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, gcap = azx_readw(chip, GCAP); snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap); - /* ATI chips seems buggy about 64bit DMA addresses */ - if (chip->driver_type == AZX_DRIVER_ATI) - gcap &= ~ICH6_GCAP_64OK; + /* disable SB600 64bit support for safety */ + if ((chip->driver_type == AZX_DRIVER_ATI) || + (chip->driver_type == AZX_DRIVER_ATIHDMI)) { + struct pci_dev *p_smbus; + p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_SBX00_SMBUS, + NULL); + if (p_smbus) { + if (p_smbus->revision < 0x30) + gcap &= ~ICH6_GCAP_64OK; + pci_dev_put(p_smbus); + } + } /* allow 64bit DMA address if supported by H/W */ if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) -- GitLab From 83c2099f5e1f0a4621ed4f20fc539069c636a24b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Wed, 8 Jul 2009 10:15:41 +0300 Subject: [PATCH 0842/1002] UBI: fix compilation warnings The recent "UBI: fix NOR flash recovery" introduced compilation warnings which were immediately spotted by our linux-next keeper. This patch fixes them. Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> --- drivers/mtd/ubi/io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index c3bd2e34c6420..4cb69925d8d96 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -481,16 +481,16 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) uint32_t data = 0; addr = (loff_t)pnum * ubi->peb_size; - err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data); + err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); if (err) { - ubi_err("error %d while writing 4 bytes to PEB %d:0, written " + ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " "%zd bytes", err, pnum, 0, written); ubi_dbg_dump_stack(); return err; } addr += ubi->vid_hdr_aloffset; - err = ubi->mtd->write(ubi->mtd, addr, 4, &written, &data); + err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); if (err) { ubi_err("error %d while writing 4 bytes to PEB %d:%d, written " "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written); -- GitLab From 00024be9689963c55cf2ab10ce3fb4502016c09a Mon Sep 17 00:00:00 2001 From: Peter Chubb <peter.chubb@nicta.com.au> Date: Wed, 8 Jul 2009 13:20:13 +0200 Subject: [PATCH 0843/1002] x86: Fix resume from suspend when CONFIG_CC_STACKPROTECTOR Patch 08687aec71bc9134fe336e561f6did877bacf74fc0a (x86: unify power/cpu_(32|64).c) renamed cpu_32.c to cpu.c, but did not update the special compilation flags for the file for the new name. This patch fixes the compilation flags, and therefore fixes resume from suspend on my Acer Aspire One. [rjw: The regression from 2.6.30 fixed by this patch is tracked as http://bugzilla.kernel.org/show_bug.cgi?id=13661] Signed-off-by: Peter Chubb <peterc@nicta.com.au> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- arch/x86/power/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile index de2abbd075448..a6a198c336238 100644 --- a/arch/x86/power/Makefile +++ b/arch/x86/power/Makefile @@ -1,7 +1,7 @@ # __restore_processor_state() restores %gs after S3 resume and so should not # itself be stack-protected nostackp := $(call cc-option, -fno-stack-protector) -CFLAGS_cpu_$(BITS).o := $(nostackp) +CFLAGS_cpu.o := $(nostackp) obj-$(CONFIG_PM_SLEEP) += cpu.o obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o -- GitLab From 886a7a3371da8ee46a13f8e598a536bd8765b837 Mon Sep 17 00:00:00 2001 From: Sebastian Ott <sebott@linux.vnet.ibm.com> Date: Wed, 8 Jul 2009 13:26:05 +0200 Subject: [PATCH 0844/1002] PM: Clear -EAGAIN in dpm_prepare When the last device in the dpm list is unregistered directly after its prepare() callback returned with -EAGAIN, the return code is passed to the calling function, resulting in a suspend failure. Prevent this by clearing the return code after -EAGAIN. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> --- drivers/base/power/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index fae7254589817..58a3e572f2c90 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -762,6 +762,7 @@ static int dpm_prepare(pm_message_t state) dev->power.status = DPM_ON; if (error == -EAGAIN) { put_device(dev); + error = 0; continue; } printk(KERN_ERR "PM: Failed to prepare device %s " -- GitLab From 508f711090e06477081fd94cb9298b1b14dda9ff Mon Sep 17 00:00:00 2001 From: Darren Salt <linux@youmustbejoking.demon.co.uk> Date: Wed, 8 Jul 2009 15:29:49 +0100 Subject: [PATCH 0845/1002] ALSA: hda - Missing volume controls for Intel HDA (ALC269/EeePC) There is a regression, introduced in aa202455eec51699e44f658530728162cefa1307 (in alsa-kernel) which I noticed when trying to use the headphone socket on my EeeCPC 901: the output was *very* quiet, practically silent. This patch corrects the control types to that which was obviously intended in the referenced commit. Signed-off-by: Darren Salt <linux@youmustbejoking.demon.co.uk> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e661b21354bed..c6c3d4a4d6486 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -12878,9 +12878,9 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { static struct snd_kcontrol_new alc269_eeepc_mixer[] = { HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), { } /* end */ }; -- GitLab From e9bf0cc7cbfbf3952cdf8028aa0d348d09ecdba1 Mon Sep 17 00:00:00 2001 From: Parag Warudkar <parag.lkml@gmail.com> Date: Wed, 8 Jul 2009 11:46:02 -0400 Subject: [PATCH 0846/1002] elfcore.h : Fix UML build breakage Commit a65e7bfcd74e4c0939f235d2bf9f48ddb3a57991 broke the UML build with the following error - In file included from fs/proc/kcore.c:17: include/linux/elfcore.h: In function 'elf_core_copy_task_regs': include/linux/elfcore.h:129: error: implicit declaration of function 'task_pt_regs' Fix this by restoring the previous behavior of returning 0 for all arches like UML that don't define task_pt_regs. Signed-off-by: Parag Warudkar <parag.lkml@gmail.com> Acked-by: Amerigo Wang <xiyou.wangcong@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/elfcore.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 03ec167798022..00d6a68d04215 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -122,10 +122,9 @@ static inline void elf_core_copy_kernel_regs(elf_gregset_t *elfregs, struct pt_r static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs) { -#ifdef ELF_CORE_COPY_TASK_REGS - +#if defined (ELF_CORE_COPY_TASK_REGS) return ELF_CORE_COPY_TASK_REGS(t, elfregs); -#else +#elif defined (task_pt_regs) elf_core_copy_regs(elfregs, task_pt_regs(t)); #endif return 0; -- GitLab From 0c8ddf7f8bf770cf49086af85078c4660d387c55 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 7 Jul 2009 19:07:57 +0200 Subject: [PATCH 0847/1002] i810fb: fix regression with uninitalized fb_info->mm_lock mutex Remove redundant call to the encode_fix() before i810 frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/i810/i810_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 71960672d7214..5743ea25e8188 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -2060,8 +2060,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, fb_var_to_videomode(&mode, &info->var); fb_add_videomode(&mode, &info->modelist); - encode_fix(&info->fix, info); - + i810fb_init_ringbuffer(info); err = register_framebuffer(info); -- GitLab From feaa61e49b126c2206051a234b8f14ccc75b9f61 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 7 Jul 2009 19:15:16 +0200 Subject: [PATCH 0848/1002] atafb: fix regression with uninitalized fb_info->mm_lock mutex Remove redundant locking of the fb_info->mm_lock mutex before the frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/atafb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 497ff8af03edf..8cd279be74e5d 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2405,6 +2405,9 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) return 0; } +/* fbhw->encode_fix() must be called with fb_info->mm_lock held + * if it is called after the register_framebuffer() - not a case here + */ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) { struct atafb_par par; @@ -2414,9 +2417,7 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) if (err) return err; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - mutex_lock(&info->mm_lock); err = fbhw->encode_fix(fix, &par); - mutex_unlock(&info->mm_lock); return err; } -- GitLab From f1b9c339bf30c90114b7c8f285d25e67c7080f90 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 7 Jul 2009 19:24:54 +0200 Subject: [PATCH 0849/1002] w100fb: fix regression with uninitalized fb_info->mm_lock mutex Remove redundant call to the w100fb_set_par() before w100 frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/w100fb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 8a141c2c637bf..2376f688ec8b6 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -748,8 +748,6 @@ int __init w100fb_probe(struct platform_device *pdev) goto out; } - w100fb_set_par(info); - if (register_framebuffer(info) < 0) { err = -EINVAL; goto out; -- GitLab From d7272e5bd9ead4389849db9749b8c4dabd459dd1 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 7 Jul 2009 22:06:48 +0200 Subject: [PATCH 0850/1002] matroxfb: fix regression with uninitalized fb_info->mm_lock mutex Remove redundant call to the matroxfb_update_fix() before matrox frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/matrox/matroxfb_base.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 76bc51b616d1c..721a87dc8cfca 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1876,7 +1876,6 @@ static int initMatrox2(WPMINFO struct board* b){ } matroxfb_init_fix(PMINFO2); ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); - matroxfb_update_fix(PMINFO2); /* Normalize values (namely yres_virtual) */ matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over -- GitLab From 99f5d48b98fb52db6da379c1b1fd6c87438ee45a Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Tue, 7 Jul 2009 22:34:13 +0200 Subject: [PATCH 0851/1002] matroxfb: fix regression with uninitalized fb_info->mm_lock mutex (second head) Remove redundant locking by the mm_lock mutex before a second head of matrox framebuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/matrox/matroxfb_crtc2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 909e10a11898b..ebcb5c6b4962b 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -289,16 +289,18 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { #undef m2info } +/* + * This function is called before the register_framebuffer so + * no locking is needed. + */ static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; strcpy(fix->id, "MATROX DH"); - mutex_lock(&m2info->fbcon.mm_lock); fix->smem_start = m2info->video.base; fix->smem_len = m2info->video.len_usable; - mutex_unlock(&m2info->fbcon.mm_lock); fix->ypanstep = 1; fix->ywrapstep = 0; fix->xpanstep = 8; /* TBD */ -- GitLab From 6c96895e999f5c44a95a5cad6a6e32e7bd6e28b6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Wed, 8 Jul 2009 09:20:11 -0700 Subject: [PATCH 0852/1002] Revert "fb: Initialize fb_info mutexes in framebuffer_alloc()" This reverts commit 4148df9b0f38bdd362dd91d52076926c11cbe5a9. Let's hope that the mm_lock initialization is now correct with all drivers, following Krzysztof's patches. Requested-by: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/fbmem.c | 2 ++ drivers/video/fbsysfs.c | 3 --- drivers/video/matrox/matroxfb_base.c | 1 - drivers/video/sm501fb.c | 2 ++ 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 53eb39652791d..53ea05645ff8e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1513,6 +1513,8 @@ register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; + mutex_init(&fb_info->lock); + mutex_init(&fb_info->mm_lock); fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index afc04df39a038..d4a2c11d98097 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -62,9 +62,6 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) mutex_init(&info->bl_curve_mutex); #endif - mutex_init(&info->lock); - mutex_init(&info->mm_lock); - return info; #undef PADDING #undef BYTES_PER_LONG diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 721a87dc8cfca..0c1049b308bf3 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -2082,7 +2082,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm spin_lock_init(&ACCESS_FBINFO(lock.accel)); init_rwsem(&ACCESS_FBINFO(crtc2.lock)); init_rwsem(&ACCESS_FBINFO(altout.lock)); - mutex_init(&ACCESS_FBINFO(fbcon).lock); mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); ACCESS_FBINFO(irq_flags) = 0; init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 98f24f0ec00df..16d4f4c7d52b5 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1624,6 +1624,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info, if (!fbi) return 0; + mutex_init(&info->fb[head]->mm_lock); + ret = sm501fb_init_fb(info->fb[head], head, drvname); if (ret) { dev_err(info->dev, "cannot initialise fb %s\n", drvname); -- GitLab From b43f3cbd21ffbd719fd4fa6642bfe6af255ded34 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan <adobriyan@gmail.com> Date: Wed, 8 Jul 2009 01:54:37 +0400 Subject: [PATCH 0853/1002] headers: mnt_namespace.h redux Fix various silly problems wrt mnt_namespace.h: - exit_mnt_ns() isn't used, remove it - done that, sched.h and nsproxy.h inclusions aren't needed - mount.h inclusion was need for vfsmount_lock, but no longer - remove mnt_namespace.h inclusion from files which don't use anything from mnt_namespace.h Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/afs/mntpt.c | 1 - fs/namespace.c | 1 + fs/nfs/getroot.c | 1 - fs/reiserfs/super.c | 1 - include/linux/mnt_namespace.h | 13 ++----------- kernel/exit.c | 1 - kernel/fork.c | 1 - kernel/kmod.c | 1 - 8 files changed, 3 insertions(+), 17 deletions(-) diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index c52be53f69462..5ffb570cd3a8e 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -17,7 +17,6 @@ #include <linux/pagemap.h> #include <linux/mount.h> #include <linux/namei.h> -#include <linux/mnt_namespace.h> #include "internal.h" diff --git a/fs/namespace.c b/fs/namespace.c index 3dc283fd4716b..277c28a63ead1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -22,6 +22,7 @@ #include <linux/seq_file.h> #include <linux/mnt_namespace.h> #include <linux/namei.h> +#include <linux/nsproxy.h> #include <linux/security.h> #include <linux/mount.h> #include <linux/ramfs.h> diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 46177cb870640..b35d2a616066a 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -30,7 +30,6 @@ #include <linux/nfs_idmap.h> #include <linux/vfs.h> #include <linux/namei.h> -#include <linux/mnt_namespace.h> #include <linux/security.h> #include <asm/system.h> diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d3aeb061612bf..7adea74d6a8ac 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -24,7 +24,6 @@ #include <linux/exportfs.h> #include <linux/quotaops.h> #include <linux/vfs.h> -#include <linux/mnt_namespace.h> #include <linux/mount.h> #include <linux/namei.h> #include <linux/crc32.h> diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h index 3beb2592b03f5..d74785c2393ad 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h @@ -2,10 +2,9 @@ #define _NAMESPACE_H_ #ifdef __KERNEL__ -#include <linux/mount.h> -#include <linux/sched.h> -#include <linux/nsproxy.h> +#include <linux/path.h> #include <linux/seq_file.h> +#include <linux/wait.h> struct mnt_namespace { atomic_t count; @@ -28,14 +27,6 @@ extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt); extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, struct fs_struct *); extern void put_mnt_ns(struct mnt_namespace *ns); - -static inline void exit_mnt_ns(struct task_struct *p) -{ - struct mnt_namespace *ns = p->nsproxy->mnt_ns; - if (ns) - put_mnt_ns(ns); -} - static inline void get_mnt_ns(struct mnt_namespace *ns) { atomic_inc(&ns->count); diff --git a/kernel/exit.c b/kernel/exit.c index 628d41f0dd54e..869dc221733e2 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -12,7 +12,6 @@ #include <linux/completion.h> #include <linux/personality.h> #include <linux/tty.h> -#include <linux/mnt_namespace.h> #include <linux/iocontext.h> #include <linux/key.h> #include <linux/security.h> diff --git a/kernel/fork.c b/kernel/fork.c index 467746b3f0aa2..bd2959228871d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/vmalloc.h> #include <linux/completion.h> -#include <linux/mnt_namespace.h> #include <linux/personality.h> #include <linux/mempolicy.h> #include <linux/sem.h> diff --git a/kernel/kmod.c b/kernel/kmod.c index 7e95bedb2bfc1..385c31a1bdbf3 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -24,7 +24,6 @@ #include <linux/unistd.h> #include <linux/kmod.h> #include <linux/slab.h> -#include <linux/mnt_namespace.h> #include <linux/completion.h> #include <linux/file.h> #include <linux/fdtable.h> -- GitLab From d5ce5b40bc66880d1732461d4b47d7fc3331ed30 Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Wed, 8 Jul 2009 11:17:34 +0100 Subject: [PATCH 0854/1002] Free the memory allocated by memdup_user() in fs/sysfs/bin.c Commit 1c8542c7bb replaced kmalloc() with memdup_user() in the write() function but also dropped the kfree(temp). The memdup_user() function allocates memory which is never freed. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Parag Warudkar <parag.warudkar@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/sysfs/bin.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 9345806c8853e..2524714bece1b 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -171,6 +171,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, if (count > 0) *off = offs + count; + kfree(temp); return count; } -- GitLab From 0f2f2221b4ad816567394a52643963428fd353cd Mon Sep 17 00:00:00 2001 From: Catalin Marinas <catalin.marinas@arm.com> Date: Wed, 8 Jul 2009 11:17:40 +0100 Subject: [PATCH 0855/1002] Free struct device in fw_dev_release() The f_dev in _request_firmware() is allocated via the fw_setup_device() and fw_register_device() calls and its class set to firmware_class (the class release function is fw_dev_release). Commit 6acf70f078ca replaced the kfree(dev) in fw_dev_release() with a put_device() call but my understanding is that the release function is called via put_device -> kobject_put -> kref_put -> koject_release etc. and it should call kfree since it's the last to see this device structure alive. Because of that, the _request_firmware() function on its -ENOENT error path only calls device_unregister(f_dev) which would eventually call fw_dev_release() but there is no kfree (the subsequent put_device call would just make the kref negative). Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> Acked-by: Ming Lei <tom.leiming@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/base/firmware_class.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ddeb819c8f878..fc466531260e9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -357,7 +357,7 @@ static void fw_dev_release(struct device *dev) kfree(fw_priv->pages); kfree(fw_priv->fw_id); kfree(fw_priv); - put_device(dev); + kfree(dev); module_put(THIS_MODULE); } @@ -408,13 +408,11 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, if (retval) { dev_err(device, "%s: device_register failed\n", __func__); put_device(f_dev); - goto error_kfree_fw_id; + return retval; } *dev_p = f_dev; return 0; -error_kfree_fw_id: - kfree(fw_priv->fw_id); error_kfree: kfree(f_dev); kfree(fw_priv); -- GitLab From 4b99d3527041bec1abe9903263a3a1b7d2ba0c4a Mon Sep 17 00:00:00 2001 From: Sheng Yang <sheng@linux.intel.com> Date: Wed, 8 Jul 2009 11:52:52 +0100 Subject: [PATCH 0856/1002] intel-iommu: Fix intel_iommu_unmap_range() with size 0 After some API change, intel_iommu_unmap_range() introduced a assumption that parameter size != 0, otherwise the dma_pte_clean_range() would have a overflowed argument. But the user like KVM don't have this assumption before, then some BUG() triggered. Fix it by ignoring size = 0. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/pci/intel-iommu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 360fb67a30d7a..ebc9b8dca881f 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3600,6 +3600,9 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain, { struct dmar_domain *dmar_domain = domain->priv; + if (!size) + return; + dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, (iova + size - 1) >> VTD_PAGE_SHIFT); -- GitLab From d945cb9cce20ac7143c2de8d88b187f62db99bdc Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Tue, 7 Jul 2009 16:39:41 +0100 Subject: [PATCH 0857/1002] pty: Rework the pty layer to use the normal buffering logic This fixes the ppp problems and various other issues with call locking caused by one side of a pty called in one locking context trying to match another with differing rules on the other side. We also get a big slack space to work with that means we can bury the flow control deadlock case for any conceivable real world situation. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/char/pty.c | 154 +++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 95 deletions(-) diff --git a/drivers/char/pty.c b/drivers/char/pty.c index daebe1ba43d42..9d1b4f548f677 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -75,114 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp) */ static void pty_unthrottle(struct tty_struct *tty) { - struct tty_struct *o_tty = tty->link; - - if (!o_tty) - return; - - tty_wakeup(o_tty); + tty_wakeup(tty->link); set_bit(TTY_THROTTLED, &tty->flags); } -/* - * WSH 05/24/97: modified to - * (1) use space in tty->flip instead of a shared temp buffer - * The flip buffers aren't being used for a pty, so there's lots - * of space available. The buffer is protected by a per-pty - * semaphore that should almost never come under contention. - * (2) avoid redundant copying for cases where count >> receive_room - * N.B. Calls from user space may now return an error code instead of - * a count. +/** + * pty_space - report space left for writing + * @to: tty we are writing into * - * FIXME: Our pty_write method is called with our ldisc lock held but - * not our partners. We can't just wait on the other one blindly without - * risking deadlocks. At some point when everything has settled down we need - * to look into making pty_write at least able to sleep over an ldisc change. + * The tty buffers allow 64K but we sneak a peak and clip at 8K this + * allows a lot of overspill room for echo and other fun messes to + * be handled properly + */ + +static int pty_space(struct tty_struct *to) +{ + int n = 8192 - to->buf.memory_used; + if (n < 0) + return 0; + return n; +} + +/** + * pty_write - write to a pty + * @tty: the tty we write from + * @buf: kernel buffer of data + * @count: bytes to write * - * The return on no ldisc is a bit counter intuitive but the logic works - * like this. During an ldisc change the other end will flush its buffers. We - * thus return the full length which is identical to the case where we had - * proper locking and happened to queue the bytes just before the flush during - * the ldisc change. + * Our "hardware" write method. Data is coming from the ldisc which + * may be in a non sleeping state. We simply throw this at the other + * end of the link as if we were an IRQ handler receiving stuff for + * the other side of the pty/tty pair. */ + static int pty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - struct tty_ldisc *ld; - int c = count; + int c; - if (!to || tty->stopped) + if (tty->stopped) return 0; - ld = tty_ldisc_ref(to); - - if (ld) { - c = to->receive_room; - if (c > count) - c = count; - ld->ops->receive_buf(to, buf, NULL, c); - tty_ldisc_deref(ld); + + /* This isn't locked but our 8K is quite sloppy so no + big deal */ + + c = pty_space(to); + if (c > count) + c = count; + if (c > 0) { + /* Stuff the data into the input queue of the other end */ + c = tty_insert_flip_string(to, buf, c); + /* And shovel */ + tty_flip_buffer_push(to); + tty_wakeup(tty); } return c; } +/** + * pty_write_room - write space + * @tty: tty we are writing from + * + * Report how many bytes the ldisc can send into the queue for + * the other device. + */ + static int pty_write_room(struct tty_struct *tty) { - struct tty_struct *to = tty->link; - - if (!to || tty->stopped) - return 0; - - return to->receive_room; + return pty_space(tty->link); } -/* - * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior - * The chars_in_buffer() value is used by the ldisc select() function - * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). - * The pty driver chars_in_buffer() Master/Slave must behave differently: - * - * The Master side needs to allow typed-ahead commands to accumulate - * while being canonicalized, so we report "our buffer" as empty until - * some threshold is reached, and then report the count. (Any count > - * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock - * the count returned must be 0 if no canonical data is available to be - * read. (The N_TTY ldisc.chars_in_buffer now knows this.) +/** + * pty_chars_in_buffer - characters currently in our tx queue + * @tty: our tty * - * The Slave side passes all characters in raw mode to the Master side's - * buffer where they can be read immediately, so in this case we can - * return the true count in the buffer. + * Report how much we have in the transmit queue. As everything is + * instantly at the other end this is easy to implement. */ + static int pty_chars_in_buffer(struct tty_struct *tty) { - struct tty_struct *to = tty->link; - struct tty_ldisc *ld; - int count = 0; - - /* We should get the line discipline lock for "tty->link" */ - if (!to) - return 0; - /* We cannot take a sleeping reference here without deadlocking with - an ldisc change - but it doesn't really matter */ - ld = tty_ldisc_ref(to); - if (ld == NULL) - return 0; - - /* The ldisc must report 0 if no characters available to be read */ - if (ld->ops->chars_in_buffer) - count = ld->ops->chars_in_buffer(to); - - tty_ldisc_deref(ld); - - if (tty->driver->subtype == PTY_TYPE_SLAVE) - return count; - - /* Master side driver ... if the other side's read buffer is less than - * half full, return 0 to allow writers to proceed; otherwise return - * the count. This leaves a comfortable margin to avoid overflow, - * and still allows half a buffer's worth of typed-ahead commands. - */ - return (count < N_TTY_BUF_SIZE/2) ? 0 : count; + return 0; } /* Set the lock flag on a pty */ @@ -202,20 +176,10 @@ static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; unsigned long flags; - struct tty_ldisc *ld; if (!to) return; - ld = tty_ldisc_ref(to); - - /* The other end is changing discipline */ - if (!ld) - return; - - if (ld->ops->flush_buffer) - to->ldisc->ops->flush_buffer(to); - tty_ldisc_deref(ld); - + /* tty_buffer_flush(to); FIXME */ if (to->packet) { spin_lock_irqsave(&tty->ctrl_lock, flags); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; -- GitLab From e3288775ff63900fbb7db505f2b9a1bee98f07df Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Tue, 7 Jul 2009 16:39:54 +0100 Subject: [PATCH 0858/1002] tty: maintainers data was edited wrongly by someone Move tty entries to tty not trivial. Noted by David Brownell. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- MAINTAINERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 381190c7949ce..e4b1a3d596cc0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5803,17 +5803,17 @@ P: Jiri Kosina M: trivial@kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git S: Maintained -F: drivers/char/tty_* -F: drivers/serial/serial_core.c -F: include/linux/serial_core.h -F: include/linux/serial.h -F: include/linux/tty.h TTY LAYER P: Alan Cox M: alan@lxorguk.ukuu.org.uk S: Maintained T: stgit http://zeniv.linux.org.uk/~alan/ttydev/ +F: drivers/char/tty_* +F: drivers/serial/serial_core.c +F: include/linux/serial_core.h +F: include/linux/serial.h +F: include/linux/tty.h TULIP NETWORK DRIVERS P: Grant Grundler -- GitLab From ad361c9884e809340f6daca80d56a9e9c871690a Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 6 Jul 2009 13:05:40 -0700 Subject: [PATCH 0859/1002] Remove multiple KERN_ prefixes from printk formats Commit 5fd29d6ccbc98884569d6f3105aeca70858b3e0f ("printk: clean up handling of log-levels and newlines") changed printk semantics. printk lines with multiple KERN_<level> prefixes are no longer emitted as before the patch. <level> is now included in the output on each additional use. Remove all uses of multiple KERN_<level>s in formats. Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/avr32/kernel/traps.c | 13 +++--- arch/blackfin/kernel/setup.c | 41 ++++++++++--------- arch/blackfin/kernel/traps.c | 34 +++++++-------- arch/m68knommu/kernel/process.c | 21 +++++----- arch/m68knommu/kernel/traps.c | 6 +-- arch/mn10300/kernel/traps.c | 21 ++++------ arch/parisc/kernel/process.c | 2 +- arch/parisc/kernel/traps.c | 20 ++++----- arch/um/kernel/sysrq.c | 4 +- arch/x86/kernel/apic/io_apic.c | 1 - arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 2 +- arch/x86/kernel/cpu/mcheck/mce.c | 12 +++--- arch/x86/kernel/e820.c | 7 ++-- arch/x86/kernel/pci-gart_64.c | 2 +- arch/x86/mm/fault.c | 9 ++-- arch/xtensa/kernel/traps.c | 6 +-- drivers/block/amiflop.c | 2 +- drivers/block/xsysace.c | 7 ++-- drivers/char/hw_random/intel-rng.c | 9 ++-- drivers/char/isicom.c | 16 ++++---- drivers/i2c/busses/i2c-ibm_iic.c | 9 ++-- drivers/md/md.c | 18 ++++---- drivers/misc/sgi-xp/xpnet.c | 4 +- drivers/net/a2065.c | 12 +----- drivers/net/arcnet/arcnet.c | 26 +++++------- drivers/net/bmac.c | 7 ++-- drivers/net/bnx2x_main.c | 7 ++-- drivers/net/dl2k.c | 17 ++++---- drivers/net/epic100.c | 5 +-- drivers/net/fealnx.c | 15 ++++--- drivers/net/hamachi.c | 23 ++++++----- drivers/net/hamradio/baycom_epp.c | 2 +- drivers/net/hamradio/baycom_par.c | 2 +- drivers/net/hamradio/baycom_ser_fdx.c | 2 +- drivers/net/hamradio/baycom_ser_hdx.c | 2 +- drivers/net/natsemi.c | 4 +- drivers/net/ne.c | 2 +- drivers/net/pci-skeleton.c | 2 +- drivers/net/pcmcia/ibmtr_cs.c | 13 +++--- drivers/net/pcmcia/nmclan_cs.c | 15 +++---- drivers/net/pcnet32.c | 50 +++++++++++------------ drivers/net/starfire.c | 2 +- drivers/net/sundance.c | 6 +-- drivers/net/tsi108_eth.c | 8 ++-- drivers/net/tulip/de2104x.c | 7 ++-- drivers/net/tulip/tulip_core.c | 14 ++++--- drivers/net/tulip/winbond-840.c | 6 +-- drivers/net/wan/hd64570.c | 3 +- drivers/net/wan/hd64572.c | 3 +- drivers/net/wan/sbni.c | 8 ++-- drivers/net/wireless/ray_cs.c | 9 ++-- drivers/net/wireless/wavelan_cs.c | 13 +----- drivers/net/yellowfin.c | 23 ++++++----- drivers/parisc/eisa_enumerator.c | 14 +++---- drivers/pcmcia/tcic.c | 3 +- drivers/scsi/atari_NCR5380.c | 3 +- drivers/scsi/mac53c94.c | 5 ++- drivers/scsi/sg.c | 2 +- drivers/scsi/sun3_NCR5380.c | 3 +- drivers/serial/8250_pci.c | 11 ++--- drivers/ssb/pcmcia.c | 4 +- drivers/usb/core/hcd.c | 2 +- drivers/video/amba-clcd.c | 7 ++-- drivers/video/matrox/matroxfb_DAC1064.c | 4 +- drivers/video/matrox/matroxfb_Ti3026.c | 4 +- drivers/video/stifb.c | 7 ++-- fs/jffs2/erase.c | 10 +++-- kernel/module.c | 6 +-- sound/pci/emu10k1/p16v.c | 2 +- sound/usb/usx2y/usbusx2yaudio.c | 7 ++-- 70 files changed, 330 insertions(+), 338 deletions(-) diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 6e3d491184eab..b91b2044af9c9 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -32,22 +32,25 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); - printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG, + printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); + + printk(KERN_EMERG); + #ifdef CONFIG_PREEMPT - printk("PREEMPT "); + printk(KERN_CONT "PREEMPT "); #endif #ifdef CONFIG_FRAME_POINTER - printk("FRAME_POINTER "); + printk(KERN_CONT "FRAME_POINTER "); #endif if (current_cpu_data.features & AVR32_FEATURE_OCD) { unsigned long did = ocd_read(DID); - printk("chip: 0x%03lx:0x%04lx rev %lu\n", + printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n", (did >> 1) & 0x7ff, (did >> 12) & 0x7fff, (did >> 28) & 0xf); } else { - printk("cpu: arch %u r%u / core %u r%u\n", + printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n", current_cpu_data.arch_type, current_cpu_data.arch_revision, current_cpu_data.cpu_type, diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 298f023bcc09b..6136c33e919f7 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -408,13 +408,14 @@ static void __init print_memory_map(char *who) bfin_memmap.map[i].addr + bfin_memmap.map[i].size); switch (bfin_memmap.map[i].type) { case BFIN_MEMMAP_RAM: - printk("(usable)\n"); - break; + printk(KERN_CONT "(usable)\n"); + break; case BFIN_MEMMAP_RESERVED: - printk("(reserved)\n"); - break; - default: printk("type %lu\n", bfin_memmap.map[i].type); - break; + printk(KERN_CONT "(reserved)\n"); + break; + default: + printk(KERN_CONT "type %lu\n", bfin_memmap.map[i].type); + break; } } } @@ -614,19 +615,19 @@ static __init void memory_setup(void) printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); printk(KERN_INFO "Memory map:\n" - KERN_INFO " fixedcode = 0x%p-0x%p\n" - KERN_INFO " text = 0x%p-0x%p\n" - KERN_INFO " rodata = 0x%p-0x%p\n" - KERN_INFO " bss = 0x%p-0x%p\n" - KERN_INFO " data = 0x%p-0x%p\n" - KERN_INFO " stack = 0x%p-0x%p\n" - KERN_INFO " init = 0x%p-0x%p\n" - KERN_INFO " available = 0x%p-0x%p\n" + " fixedcode = 0x%p-0x%p\n" + " text = 0x%p-0x%p\n" + " rodata = 0x%p-0x%p\n" + " bss = 0x%p-0x%p\n" + " data = 0x%p-0x%p\n" + " stack = 0x%p-0x%p\n" + " init = 0x%p-0x%p\n" + " available = 0x%p-0x%p\n" #ifdef CONFIG_MTD_UCLINUX - KERN_INFO " rootfs = 0x%p-0x%p\n" + " rootfs = 0x%p-0x%p\n" #endif #if DMA_UNCACHED_REGION > 0 - KERN_INFO " DMA Zone = 0x%p-0x%p\n" + " DMA Zone = 0x%p-0x%p\n" #endif , (void *)FIXED_CODE_START, (void *)FIXED_CODE_END, _stext, _etext, @@ -859,13 +860,13 @@ void __init setup_arch(char **cmdline_p) #endif printk(KERN_INFO "Hardware Trace "); if (bfin_read_TBUFCTL() & 0x1) - printk("Active "); + printk(KERN_CONT "Active "); else - printk("Off "); + printk(KERN_CONT "Off "); if (bfin_read_TBUFCTL() & 0x2) - printk("and Enabled\n"); + printk(KERN_CONT "and Enabled\n"); else - printk("and Disabled\n"); + printk(KERN_CONT "and Disabled\n"); #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) /* we need to initialize the Flashrom device here since we might diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8eeb457ce5d5f..8a1caf2bb5b9d 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -212,7 +212,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) console_verbose(); oops_in_progress = 1; #ifdef CONFIG_DEBUG_VERBOSE - printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); + printk(KERN_EMERG "Double Fault\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { unsigned int cpu = smp_processor_id(); @@ -583,15 +583,14 @@ asmlinkage void trap_c(struct pt_regs *fp) #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) verbose_printk(KERN_NOTICE "No trace since you do not have " - "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" - KERN_NOTICE "\n"); + "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n"); else #endif dump_bfin_trace_buffer(); if (oops_in_progress) { /* Dump the current kernel stack */ - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); + verbose_printk(KERN_NOTICE "Kernel Stack\n"); show_stack(current, NULL); print_modules(); #ifndef CONFIG_ACCESS_CHECK @@ -906,7 +905,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) ret_addr = 0; if (!j && i % 8 == 0) - printk("\n" KERN_NOTICE "%p:",addr); + printk(KERN_NOTICE "%p:",addr); /* if it is an odd address, or zero, just skip it */ if (*addr & 0x1 || !*addr) @@ -996,9 +995,9 @@ void dump_bfin_process(struct pt_regs *fp) printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu); if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) - verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" - KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" - KERN_NOTICE "\n", + verbose_printk(KERN_NOTICE + "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + " BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n", (void *)current->mm->start_code, (void *)current->mm->end_code, (void *)current->mm->start_data, @@ -1009,8 +1008,8 @@ void dump_bfin_process(struct pt_regs *fp) else verbose_printk(KERN_NOTICE "invalid mm\n"); } else - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE - "No Valid process in current context\n"); + verbose_printk(KERN_NOTICE + "No Valid process in current context\n"); #endif } @@ -1028,7 +1027,7 @@ void dump_bfin_mem(struct pt_regs *fp) addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; addr++) { if (!((unsigned long)addr & 0xF)) - verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); + verbose_printk(KERN_NOTICE "0x%p: ", addr); if (!get_instruction(&val, addr)) { val = 0; @@ -1056,9 +1055,9 @@ void dump_bfin_mem(struct pt_regs *fp) oops_in_progress)){ verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); #ifndef CONFIG_DEBUG_HWERR - verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" - KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" - " better idea where it came from\n"); + verbose_printk(KERN_NOTICE +"The remaining message may be meaningless\n" +"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n"); #else /* If we are handling only one peripheral interrupt * and current mm and pid are valid, and the last error @@ -1114,9 +1113,10 @@ void show_regs(struct pt_regs *fp) verbose_printk(KERN_NOTICE "%s", linux_banner); - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); + verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n", + print_tainted()); verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", - (long)fp->seqstat, fp->ipend, fp->syscfg); + (long)fp->seqstat, fp->ipend, fp->syscfg); if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); @@ -1184,7 +1184,7 @@ void show_regs(struct pt_regs *fp) verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); } - verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); + verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n"); verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", fp->r0, fp->r1, fp->r2, fp->r3); verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 1e96c6eb63125..8f8f4abab2ff1 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -290,7 +290,7 @@ void dump(struct pt_regs *fp) unsigned char *tp; int i; - printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\nCURRENT PROCESS:\n\n"); printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); if (current->mm) { @@ -301,8 +301,7 @@ void dump(struct pt_regs *fp) (int) current->mm->end_data, (int) current->mm->end_data, (int) current->mm->brk); - printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n" - KERN_EMERG "\n", + printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n", (int) current->mm->start_stack, (int)(((unsigned long) current) + THREAD_SIZE)); } @@ -313,35 +312,35 @@ void dump(struct pt_regs *fp) fp->d0, fp->d1, fp->d2, fp->d3); printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", fp->d4, fp->d5, fp->a0, fp->a1); - printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x TRAPFRAME: %08x\n", + printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(), (unsigned int) fp); - printk(KERN_EMERG "\n" KERN_EMERG "CODE:"); + printk(KERN_EMERG "\nCODE:"); tp = ((unsigned char *) fp->pc) - 0x20; for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); printk(KERN_EMERG "KERNEL STACK:"); tp = ((unsigned char *) fp) - 0x40; for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); printk(KERN_EMERG "USER STACK:"); tp = (unsigned char *) (rdusp() - 0x10); for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { if ((i % 0x10) == 0) - printk("\n" KERN_EMERG "%08x: ", (int) (tp + i)); + printk(KERN_EMERG "%08x: ", (int) (tp + i)); printk("%08x ", (int) *sp++); } - printk("\n" KERN_EMERG "\n"); + printk(KERN_EMERG "\n"); } /* diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 51d325343ab58..3739c8f657d75 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -111,7 +111,7 @@ static void print_this_address(unsigned long addr, int i) if (i % 5) printk(KERN_CONT " [%08lx] ", addr); else - printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr); + printk(KERN_EMERG " [%08lx] ", addr); i++; #endif } @@ -137,8 +137,8 @@ static void __show_stack(struct task_struct *task, unsigned long *stack) if (stack + 1 + i > endstack) break; if (i % 8 == 0) - printk("\n" KERN_EMERG " "); - printk(" %08lx", *(stack + i)); + printk(KERN_EMERG " "); + printk(KERN_CONT " %08lx", *(stack + i)); } printk("\n"); i = 0; diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index 681ad8c9e4fb6..0dfdc50011241 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c @@ -136,8 +136,7 @@ void show_trace(unsigned long *sp) unsigned long *stack, addr, module_start, module_end; int i; - printk(KERN_EMERG "\n" - KERN_EMERG "Call Trace:"); + printk(KERN_EMERG "\nCall Trace:"); stack = sp; i = 0; @@ -153,7 +152,7 @@ void show_trace(unsigned long *sp) printk("\n"); #else if ((i % 6) == 0) - printk("\n" KERN_EMERG " "); + printk(KERN_EMERG " "); printk("[<%08lx>] ", addr); i++; #endif @@ -180,7 +179,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) if (((long) stack & (THREAD_SIZE - 1)) == 0) break; if ((i % 8) == 0) - printk("\n" KERN_EMERG " "); + printk(KERN_EMERG " "); printk("%08lx ", *stack++); } @@ -264,8 +263,7 @@ void show_registers(struct pt_regs *regs) show_stack(current, (unsigned long *) sp); #if 0 - printk(KERN_EMERG "\n" - KERN_EMERG "Code: "); + printk(KERN_EMERG "\nCode: "); if (regs->pc < PAGE_OFFSET) goto bad; @@ -311,16 +309,14 @@ void die(const char *str, struct pt_regs *regs, enum exception_code code) { console_verbose(); spin_lock_irq(&die_lock); - printk(KERN_EMERG "\n" - KERN_EMERG "%s: %04x\n", + printk(KERN_EMERG "\n%s: %04x\n", str, code & 0xffff); show_registers(regs); if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 && (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) { printk(KERN_EMERG "Exception in usermode interrupt handler\n"); - printk(KERN_EMERG "\n" - KERN_EMERG " Please connect to kernel debugger !!\n"); + printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n"); asm volatile ("0: bra 0b"); } @@ -429,9 +425,8 @@ asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs) { console_verbose(); - printk(KERN_EMERG "\n" - KERN_EMERG "Asynchronous I/O Bus Error\n" - KERN_EMERG "==========================\n"); + printk(KERN_EMERG "Asynchronous I/O Bus Error\n"); + printk(KERN_EMERG "==========================\n"); if (bcberr & BCBERR_BEME) printk(KERN_EMERG "- Multiple recorded errors\n"); diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 61c07078c072d..1f3aa8db02030 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -156,7 +156,7 @@ void machine_power_off(void) * software. The user has to press the button himself. */ printk(KERN_EMERG "System shut down completed.\n" - KERN_EMERG "Please power this system off now."); + "Please power this system off now."); } void (*pm_power_off)(void) = machine_power_off; diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index c32f5d6d778ec..528f0ff9b2738 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -250,15 +250,14 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) oops_enter(); /* Amuse the user in a SPARC fashion */ - if (err) printk( -KERN_CRIT " _______________________________ \n" -KERN_CRIT " < Your System ate a SPARC! Gah! >\n" -KERN_CRIT " ------------------------------- \n" -KERN_CRIT " \\ ^__^\n" -KERN_CRIT " \\ (xx)\\_______\n" -KERN_CRIT " (__)\\ )\\/\\\n" -KERN_CRIT " U ||----w |\n" -KERN_CRIT " || ||\n"); + if (err) printk(KERN_CRIT + " _______________________________ \n" + " < Your System ate a SPARC! Gah! >\n" + " ------------------------------- \n" + " \\ ^__^\n" + " (__)\\ )\\/\\\n" + " U ||----w |\n" + " || ||\n"); /* unlock the pdc lock if necessary */ pdc_emergency_unlock(); @@ -797,7 +796,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs) else printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ", code); - printk("pid=%d command='%s'\n", task_pid_nr(current), current->comm); + printk(KERN_CONT "pid=%d command='%s'\n", + task_pid_nr(current), current->comm); show_regs(regs); #endif si.si_signo = SIGSEGV; diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 56d43d0a39602..0960de54495ab 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -70,8 +70,8 @@ void show_stack(struct task_struct *task, unsigned long *esp) if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) - printk("\n" KERN_INFO " "); - printk("%08lx ", *stack++); + printk(KERN_INFO " "); + printk(KERN_CONT "%08lx ", *stack++); } show_trace(task, esp); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 8fd1efb5a0bd2..90b5e6efa938e 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1739,7 +1739,6 @@ __apicdebuginit(void) print_local_APIC(void *dummy) if (apic_verbosity == APIC_QUIET) return; - printk(KERN_DEBUG "\n"); printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index ae068f59603f4..2a50ef891000f 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -1259,7 +1259,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) { static const char ACPI_PSS_BIOS_BUG_MSG[] = KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n" - KERN_ERR FW_BUG PFX "Try again with latest BIOS.\n"; + FW_BUG PFX "Try again with latest BIOS.\n"; struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; int rc; diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index af425b83202b3..484c1e5f658e6 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -194,14 +194,14 @@ static void print_mce(struct mce *m) m->cs, m->ip); if (m->cs == __KERNEL_CS) print_symbol("{%s}", m->ip); - printk("\n"); + printk(KERN_CONT "\n"); } printk(KERN_EMERG "TSC %llx ", m->tsc); if (m->addr) - printk("ADDR %llx ", m->addr); + printk(KERN_CONT "ADDR %llx ", m->addr); if (m->misc) - printk("MISC %llx ", m->misc); - printk("\n"); + printk(KERN_CONT "MISC %llx ", m->misc); + printk(KERN_CONT "\n"); printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid); @@ -209,13 +209,13 @@ static void print_mce(struct mce *m) static void print_mce_head(void) { - printk(KERN_EMERG "\n" KERN_EMERG "HARDWARE ERROR\n"); + printk(KERN_EMERG "\nHARDWARE ERROR\n"); } static void print_mce_tail(void) { printk(KERN_EMERG "This is not a software problem!\n" - KERN_EMERG "Run through mcelog --ascii to decode and contact your hardware vendor\n"); + "Run through mcelog --ascii to decode and contact your hardware vendor\n"); } #define PANIC_TIMEOUT 5 /* 5 seconds */ diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index c4ca89d9aaf46..5cb5725b2bae2 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -627,10 +627,9 @@ __init void e820_setup_gap(void) #ifdef CONFIG_X86_64 if (!found) { gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024; - printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit " - "address range\n" - KERN_ERR "PCI: Unassigned devices with 32bit resource " - "registers may break!\n"); + printk(KERN_ERR + "PCI: Warning: Cannot find a gap in the 32bit address range\n" + "PCI: Unassigned devices with 32bit resource registers may break!\n"); } #endif diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index cfd9f90638967..d2e56b8f48e70 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -675,7 +675,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) nommu: /* Should not happen anymore */ printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n" - KERN_WARNING "falling back to iommu=soft.\n"); + "falling back to iommu=soft.\n"); return -1; } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 78a5fff857bea..85307cc6e45f9 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -426,10 +426,11 @@ static noinline int vmalloc_fault(unsigned long address) } static const char errata93_warning[] = -KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n" -KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n" -KERN_ERR "******* Please consider a BIOS update.\n" -KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n"; +KERN_ERR +"******* Your BIOS seems to not contain a fix for K8 errata #93\n" +"******* Working around it, but it may cause SEGVs or burn power.\n" +"******* Please consider a BIOS update.\n" +"******* Disabling USB legacy in the BIOS may also help.\n"; /* * No vm86 mode in 64-bit mode: diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index ba9ab9349782d..e64efac3b9db4 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -354,10 +354,10 @@ void show_regs(struct pt_regs * regs) for (i = 0; i < 16; i++) { if ((i % 8) == 0) - printk ("\n" KERN_INFO "a%02d: ", i); - printk("%08lx ", regs->areg[i]); + printk(KERN_INFO "a%02d:", i); + printk(KERN_CONT " %08lx", regs->areg[i]); } - printk("\n"); + printk(KERN_CONT "\n"); printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n", regs->pc, regs->ps, regs->depc, regs->excvaddr); diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 9c6e5b0fe894f..2f07b7c99a95b 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1645,7 +1645,7 @@ static int __init fd_probe_drives(void) { int drive,drives,nomem; - printk(KERN_INFO "FD: probing units\n" KERN_INFO "found "); + printk(KERN_INFO "FD: probing units\nfound "); drives=0; nomem=0; for(drive=0;drive<FD_MAX_UNITS;drive++) { diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index f08491a3a813b..b20abe102a2b7 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -390,9 +390,10 @@ static inline void ace_dump_mem(void *base, int len) static void ace_dump_regs(struct ace_device *ace) { - dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" - KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n" - KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", + dev_info(ace->dev, + " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" + " status:%.8x mpu_lba:%.8x busmode:%4x\n" + " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", ace_in32(ace, ACE_CTRL), ace_in(ace, ACE_SECCNTCMD), ace_in(ace, ACE_VERSION), diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5dcbe603eca2e..91b53eb1c053b 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -305,10 +305,11 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) == BIOS_CNTL_LOCK_ENABLE_MASK) { static __initdata /*const*/ char warning[] = - KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" - KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" - KERN_WARNING PFX "you are certain that your system has a functional\n" - KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; + KERN_WARNING +PFX "Firmware space is locked read-only. If you can't or\n" +PFX "don't want to disable this in firmware setup, and if\n" +PFX "you are certain that your system has a functional\n" +PFX "RNG, try using the 'no_fwh_detect' option.\n"; if (no_fwh_detect) return -ENODEV; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 4159292e35cf4..621d1184673c7 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1478,10 +1478,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, status = inw(base + 0x4); if (status != 0) { dev_warn(&pdev->dev, "Card%d rejected load header:\n" - KERN_WARNING "Address:0x%x\n" - KERN_WARNING "Count:0x%x\n" - KERN_WARNING "Status:0x%x\n", - index + 1, frame->addr, frame->count, status); + "Address:0x%x\n" + "Count:0x%x\n" + "Status:0x%x\n", + index + 1, frame->addr, frame->count, status); goto errrelfw; } outsw(base, frame->data, word_count); @@ -1526,10 +1526,10 @@ static int __devinit load_firmware(struct pci_dev *pdev, status = inw(base + 0x4); if (status != 0) { dev_warn(&pdev->dev, "Card%d rejected verify header:\n" - KERN_WARNING "Address:0x%x\n" - KERN_WARNING "Count:0x%x\n" - KERN_WARNING "Status: 0x%x\n", - index + 1, frame->addr, frame->count, status); + "Address:0x%x\n" + "Count:0x%x\n" + "Status: 0x%x\n", + index + 1, frame->addr, frame->count, status); goto errrelfw; } diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index e4476743f2033..b1bc6e277d2a1 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) { volatile struct iic_regs __iomem *iic = dev->vaddr; printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); - printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" - KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" - KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" - KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", + printk(KERN_DEBUG + " cntl = 0x%02x, mdcntl = 0x%02x\n" + " sts = 0x%02x, extsts = 0x%02x\n" + " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" + " xtcntlss = 0x%02x, directcntl = 0x%02x\n", in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), in_8(&iic->xtcntlss), in_8(&iic->directcntl)); diff --git a/drivers/md/md.c b/drivers/md/md.c index 0f4a70c43ffcb..d4351ff0849fb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1756,9 +1756,10 @@ static void print_sb_1(struct mdp_superblock_1 *sb) __u8 *uuid; uuid = sb->set_uuid; - printk(KERN_INFO "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" - ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" - KERN_INFO "md: Name: \"%s\" CT:%llu\n", + printk(KERN_INFO + "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x" + ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n" + "md: Name: \"%s\" CT:%llu\n", le32_to_cpu(sb->major_version), le32_to_cpu(sb->feature_map), uuid[0], uuid[1], uuid[2], uuid[3], @@ -1770,12 +1771,13 @@ static void print_sb_1(struct mdp_superblock_1 *sb) & MD_SUPERBLOCK_1_TIME_SEC_MASK); uuid = sb->device_uuid; - printk(KERN_INFO "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" + printk(KERN_INFO + "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu" " RO:%llu\n" - KERN_INFO "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" - ":%02x%02x%02x%02x%02x%02x\n" - KERN_INFO "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" - KERN_INFO "md: (MaxDev:%u) \n", + "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x" + ":%02x%02x%02x%02x%02x%02x\n" + "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n" + "md: (MaxDev:%u) \n", le32_to_cpu(sb->level), (unsigned long long)le64_to_cpu(sb->size), le32_to_cpu(sb->raid_disks), diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 8d1c60a3f0df9..5d778ec8cdb2a 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -235,7 +235,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg) skb->ip_summed = CHECKSUM_UNNECESSARY; dev_dbg(xpnet, "passing skb to network layer\n" - KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " + "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p " "skb->end=0x%p skb->len=%d\n", (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len); @@ -399,7 +399,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg, msg->buf_pa = xp_pa((void *)start_addr); dev_dbg(xpnet, "sending XPC message to %d:%d\n" - KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, " + "msg->buf_pa=0x%lx, msg->size=%u, " "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n", dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size, msg->leadin_ignore, msg->tailout_ignore); diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 85a18175730ba..08787f5a22a3d 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -569,16 +569,8 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) #ifdef DEBUG_DRIVER /* dump the packet */ - { - int i; - - for (i = 0; i < 64; i++) { - if ((i % 16) == 0) - printk("\n" KERN_DEBUG); - printk ("%2.2x ", skb->data [i]); - } - printk("\n"); - } + print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE, + 16, 1, skb->data, 64, true); #endif entry = lp->tx_new & lp->tx_ring_mod_mask; ib->btx_ring [entry].length = (-skblen) | 0xf000; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index d6d4ab3b430cc..7d227cdab9f8c 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -158,15 +158,12 @@ module_exit(arcnet_exit); void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) { - int i; + char hdr[32]; - printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); - for (i = 0; i < skb->len; i++) { - if (i % 16 == 0) - printk("\n" KERN_DEBUG "[%04X] ", i); - printk("%02X ", ((u_char *) skb->data)[i]); - } - printk("\n"); + /* dump the packet */ + snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc); + print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, + 16, 1, skb->data, skb->len, true); } EXPORT_SYMBOL(arcnet_dump_skb); @@ -184,6 +181,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, int i, length; unsigned long flags = 0; static uint8_t buf[512]; + char hdr[32]; /* hw.copy_from_card expects IRQ context so take the IRQ lock to keep it single threaded */ @@ -197,14 +195,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, /* if the offset[0] byte is nonzero, this is a 256-byte packet */ length = (buf[2] ? 256 : 512); - printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); - for (i = 0; i < length; i++) { - if (i % 16 == 0) - printk("\n" KERN_DEBUG "[%04X] ", i); - printk("%02X ", buf[i]); - } - printk("\n"); - + /* dump the packet */ + snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc); + print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, + 16, 1, buf, length, true); } #else diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 9578a3dfac013..a76315dc77678 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -428,10 +428,11 @@ bmac_init_phy(struct net_device *dev) printk(KERN_DEBUG "phy registers:"); for (addr = 0; addr < 32; ++addr) { if ((addr & 7) == 0) - printk("\n" KERN_DEBUG); - printk(" %.4x", bmac_mif_read(dev, addr)); + printk(KERN_DEBUG); + printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); } - printk("\n"); + print(KERN_CONT "\n"); + if (bp->is_bmac_plus) { unsigned int capable, ctrl; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 6c67be679764d..c36a5f33739f5 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -484,8 +484,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp) mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); mark = ((mark + 0x3) & ~0x3); - printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark); + printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark); + printk(KERN_ERR PFX); for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + @@ -500,7 +501,7 @@ static void bnx2x_fw_dump(struct bnx2x *bp) data[8] = 0x0; printk(KERN_CONT "%s", (char *)data); } - printk("\n" KERN_ERR PFX "end of fw dump\n"); + printk(KERN_ERR PFX "end of fw dump\n"); } static void bnx2x_panic_dump(struct bnx2x *bp) @@ -7354,7 +7355,7 @@ static void bnx2x_reset_task(struct work_struct *work) #ifdef BNX2X_STOP_ON_ERROR BNX2X_ERR("reset task called but STOP_ON_ERROR defined" " so reset not done to allow debug dump,\n" - KERN_ERR " you will need to reboot when done\n"); + " you will need to reboot when done\n"); return; #endif diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 895d72143ee04..4b6a219fecea8 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -268,8 +268,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_INFO "tx_coalesce:\t%d packets\n", tx_coalesce); if (np->coalesce) - printk(KERN_INFO "rx_coalesce:\t%d packets\n" - KERN_INFO "rx_timeout: \t%d ns\n", + printk(KERN_INFO + "rx_coalesce:\t%d packets\n" + "rx_timeout: \t%d ns\n", np->rx_coalesce, np->rx_timeout*640); if (np->vlan) printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); @@ -1522,9 +1523,9 @@ mii_get_media (struct net_device *dev) printk (KERN_INFO "Operating at 10 Mbps, "); } if (bmcr & MII_BMCR_DUPLEX_MODE) { - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } } if (np->tx_flow) @@ -1614,9 +1615,9 @@ mii_set_media (struct net_device *dev) } if (np->full_duplex) { bmcr |= MII_BMCR_DUPLEX_MODE; - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } #if 0 /* Set 1000BaseT Master/Slave setting */ @@ -1669,9 +1670,9 @@ mii_get_media_pcs (struct net_device *dev) __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR); printk (KERN_INFO "Operating at 1000 Mbps, "); if (bmcr & MII_BMCR_DUPLEX_MODE) { - printk ("Full duplex\n"); + printk (KERN_CONT "Full duplex\n"); } else { - printk ("Half duplex\n"); + printk (KERN_CONT "Half duplex\n"); } } if (np->tx_flow) diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index b60e27dfcfa7c..88d7ebf31220c 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -338,8 +338,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, #ifndef MODULE static int printed_version; if (!printed_version++) - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk(KERN_INFO "%s%s", version, version2); #endif card_idx++; @@ -1600,7 +1599,7 @@ static int __init epic_init (void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk (KERN_INFO "%s" KERN_INFO "%s", + printk (KERN_INFO "%s%s", version, version2); #endif diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 891be28a7d4f4..053fb49820b9c 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1209,17 +1209,20 @@ static void fealnx_tx_timeout(struct net_device *dev) unsigned long flags; int i; - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, ioread32(ioaddr + ISR)); + printk(KERN_WARNING + "%s: Transmit timed out, status %8.8x, resetting...\n", + dev->name, ioread32(ioaddr + ISR)); { printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int) np->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring); + printk(PR_CONT " %8.8x", + (unsigned int) np->rx_ring[i].status); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", np->tx_ring[i].status); - printk("\n"); + printk(PR_CONT " %4.4x", np->tx_ring[i].status); + printk(PR_CONT "\n"); } spin_lock_irqsave(&np->lock, flags); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 9d5b62cb30f79..d62378cbc149e 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -173,8 +173,8 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static const char version[] __devinitconst = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" -KERN_INFO " Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" -KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; +" Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" +" Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; /* IP_MF appears to be only defined in <netinet/ip.h>, however, @@ -1080,11 +1080,14 @@ static void hamachi_tx_timeout(struct net_device *dev) { printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length)); - printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); + printk(KERN_CONT " %8.8x", + le32_to_cpu(hmp->rx_ring[i].status_n_length)); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length)); - printk("\n"); + printk(KERN_CONT " %4.4x", + le32_to_cpu(hmp->tx_ring[i].status_n_length)); + printk(KERN_CONT "\n"); } /* Reinit the hardware and make sure the Rx and Tx processes @@ -1753,13 +1756,13 @@ static int hamachi_close(struct net_device *dev) #ifdef __i386__ if (hamachi_debug > 2) { - printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", + printk(KERN_DEBUG " Tx ring at %8.8x:\n", (int)hmp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %c #%d desc. %8.8x %8.8x.\n", + printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n", readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ', i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)hmp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n", @@ -1770,7 +1773,7 @@ static int hamachi_close(struct net_device *dev) u16 *addr = (u16 *) hmp->rx_skbuff[i]->data; int j; - + printk(KERN_DEBUG "Addr: "); for (j = 0; j < 0x50; j++) printk(" %4.4x", addr[j]); printk("\n"); diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 5e4b7afd06839..352703255bba8 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -68,7 +68,7 @@ static const char paranoia_str[] = KERN_ERR static const char bc_drvname[] = "baycom_epp"; static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 2e6fc4dc74b12..5f5af9a606f8a 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -102,7 +102,7 @@ static const char bc_drvname[] = "baycom_par"; static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index b6a816e60c0f7..aa4488e871b24 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c @@ -91,7 +91,7 @@ static const char bc_drvname[] = "baycom_ser_fdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c index 3bcc57acbe6d9..88c5935960202 100644 --- a/drivers/net/hamradio/baycom_ser_hdx.c +++ b/drivers/net/hamradio/baycom_ser_hdx.c @@ -79,7 +79,7 @@ static const char bc_drvname[] = "baycom_ser_hdx"; static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; +"baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c9bfe4eea189d..78c088331f570 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -130,8 +130,8 @@ static int full_duplex[MAX_UNITS]; static const char version[] __devinitconst = KERN_INFO DRV_NAME " dp8381x driver, version " DRV_VERSION ", " DRV_RELDATE "\n" - KERN_INFO " originally by Donald Becker <becker@scyld.com>\n" - KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; + " originally by Donald Becker <becker@scyld.com>\n" + " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 5c3e242428f11..992dbfffdb05e 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -321,7 +321,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) } if (ei_debug && version_printed++ == 0) - printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); + printk(KERN_INFO "%s%s", version1, version2); printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 8c1f6988f398b..89f7b2ad52311 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -105,7 +105,7 @@ IVc. Errata static char version[] __devinitdata = KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" -KERN_INFO " Support available from http://foo.com/bar/baz.html\n"; +" Support available from http://foo.com/bar/baz.html\n"; /* define to 1 to enable PIO instead of MMIO */ #undef USE_IO_OPS diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index f51944b28cfa7..06618af1a4680 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -298,14 +298,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link) strcpy(info->node.dev_name, dev->name); - printk(KERN_INFO "%s: port %#3lx, irq %d,", - dev->name, dev->base_addr, dev->irq); - printk (" mmio %#5lx,", (u_long)ti->mmio); - printk (" sram %#5lx,", (u_long)ti->sram_base << 12); - printk ("\n" KERN_INFO " hwaddr="); - for (i = 0; i < TR_ALEN; i++) - printk("%02X", dev->dev_addr[i]); - printk("\n"); + printk(KERN_INFO + "%s: port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", + dev->name, dev->base_addr, dev->irq, + (u_long)ti->mmio, (u_long)(ti->sram_base << 12), + dev->dev_addr); return 0; cs_failed: diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 02ef63ed1f99b..36de91baf2387 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1425,15 +1425,12 @@ static void BuildLAF(int *ladrf, int *adr) ladrf[byte] |= (1 << (hashcode & 7)); #ifdef PCMCIA_DEBUG - if (pc_debug > 2) { - printk(KERN_DEBUG " adr ="); - for (i = 0; i < 6; i++) - printk(" %02X", adr[i]); - printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]" - " =", hashcode); - for (i = 0; i < 8; i++) - printk(" %02X", ladrf[i]); - printk("\n"); + if (pc_debug > 2) + printk(KERN_DEBUG " adr =%pM\n", adr); + printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode); + for (i = 0; i < 8; i++) + printk(KERN_CONT " %02X", ladrf[i]); + printk(KERN_CONT "\n"); } #endif } /* BuildLAF */ diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 1c35e1d637a0e..28368157dac4e 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -485,7 +485,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, &new_ring_dma_addr); if (new_tx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Consistent memory allocation failed.\n", dev->name); return; @@ -496,7 +496,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_dma_addr_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_tx_ring; } @@ -505,7 +505,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_skb_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_lists; } @@ -563,7 +563,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, &new_ring_dma_addr); if (new_rx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Consistent memory allocation failed.\n", dev->name); return; @@ -574,7 +574,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_dma_addr_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_rx_ring; } @@ -583,7 +583,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, GFP_ATOMIC); if (!new_skb_list) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR + printk(KERN_ERR "%s: Memory allocation failed.\n", dev->name); goto free_new_lists; } @@ -1766,38 +1766,38 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) /* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) { i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i); + printk(KERN_INFO " tx_start_pt(0x%04x):", i); switch (i >> 10) { case 0: - printk(" 20 bytes,"); + printk(KERN_CONT " 20 bytes,"); break; case 1: - printk(" 64 bytes,"); + printk(KERN_CONT " 64 bytes,"); break; case 2: - printk(" 128 bytes,"); + printk(KERN_CONT " 128 bytes,"); break; case 3: - printk("~220 bytes,"); + printk(KERN_CONT "~220 bytes,"); break; } i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(" BCR18(%x):", i & 0xffff); + printk(KERN_CONT " BCR18(%x):", i & 0xffff); if (i & (1 << 5)) - printk("BurstWrEn "); + printk(KERN_CONT "BurstWrEn "); if (i & (1 << 6)) - printk("BurstRdEn "); + printk(KERN_CONT "BurstRdEn "); if (i & (1 << 7)) - printk("DWordIO "); + printk(KERN_CONT "DWordIO "); if (i & (1 << 11)) - printk("NoUFlow "); + printk(KERN_CONT "NoUFlow "); i = a->read_bcr(ioaddr, 25); - printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8); + printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 26); - printk(" SRAM_BND=0x%04x,", i << 8); + printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 27); if (i & (1 << 14)) - printk("LowLatRx"); + printk(KERN_CONT "LowLatRx"); } } @@ -1996,7 +1996,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) &lp->tx_ring_dma_addr); if (lp->tx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; @@ -2008,7 +2008,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) &lp->rx_ring_dma_addr); if (lp->rx_ring == NULL) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Consistent memory allocation failed.\n", name); return -ENOMEM; @@ -2018,7 +2018,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->tx_dma_addr) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2027,7 +2027,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->rx_dma_addr) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2036,7 +2036,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->tx_skbuff) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } @@ -2045,7 +2045,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) GFP_ATOMIC); if (!lp->rx_skbuff) { if (netif_msg_drv(lp)) - printk("\n" KERN_ERR PFX + printk(KERN_ERR PFX "%s: Memory allocation failed.\n", name); return -ENOMEM; } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 838cce8b8fff3..669253c7bd41f 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -180,7 +180,7 @@ static int full_duplex[MAX_UNITS] = {0, }; /* These identify the driver base version and may not be removed. */ static const char version[] __devinitconst = KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" -KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; +" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 545f81b34ad7e..d1521c3875b2d 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1698,13 +1698,13 @@ static int netdev_close(struct net_device *dev) #ifdef __i386__ if (netif_msg_hw(np)) { - printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", + printk(KERN_DEBUG " Tx ring at %8.8x:\n", (int)(np->tx_ring_dma)); for (i = 0; i < TX_RING_SIZE; i++) - printk(" #%d desc. %4.4x %8.8x %8.8x.\n", + printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n", i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr, np->tx_ring[i].frag[0].length); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)(np->rx_ring_dma)); for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) { printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 0f78f99f9b20c..7030bd5e9848e 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1132,7 +1132,9 @@ static int tsi108_get_mac(struct net_device *dev) } if (!is_valid_ether_addr(dev->dev_addr)) { - printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2); + printk(KERN_ERR + "%s: Invalid MAC address. word1: %08x, word2: %08x\n", + dev->name, word1, word2); return -EINVAL; } @@ -1201,8 +1203,8 @@ static void tsi108_set_rx_mode(struct net_device *dev) __set_bit(hash, &data->mc_hash[0]); } else { printk(KERN_ERR - "%s: got multicast address of length %d " - "instead of 6.\n", dev->name, + "%s: got multicast address of length %d instead of 6.\n", + dev->name, mc->dmi_addrlen); } diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 81f054dbb88dd..ef49744a50852 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -944,9 +944,10 @@ static void de_set_media (struct de_private *de) macmode &= ~FullDuplex; if (netif_msg_link(de)) { - printk(KERN_INFO "%s: set link %s\n" - KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" - KERN_INFO "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", + printk(KERN_INFO + "%s: set link %s\n" + "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" + "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", de->dev->name, media_name[media], de->dev->name, dr32(MacMode), dr32(SIAStatus), dr32(CSR13), dr32(CSR14), dr32(CSR15), diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 2abb5d3becc6d..99a63649f4fcd 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -570,16 +570,18 @@ static void tulip_tx_timeout(struct net_device *dev) (unsigned int)tp->rx_ring[i].buffer2, buf[0], buf[1], buf[2]); for (j = 0; buf[j] != 0xee && j < 1600; j++) - if (j < 100) printk(" %2.2x", buf[j]); - printk(" j=%d.\n", j); + if (j < 100) + printk(KERN_CONT " %2.2x", buf[j]); + printk(KERN_CONT " j=%d.\n", j); } printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); - printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); + printk(KERN_CONT " %8.8x", + (unsigned int)tp->rx_ring[i].status); + printk(KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); - printk("\n"); + printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status); + printk(KERN_CONT "\n"); } #endif diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 842b1a2c40d4a..0f15773dae528 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -142,7 +142,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static const char version[] __initconst = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker <becker@scyld.com>\n" - KERN_INFO " http://www.scyld.com/network/drivers.html\n"; + " http://www.scyld.com/network/drivers.html\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver"); @@ -939,7 +939,7 @@ static void tx_timeout(struct net_device *dev) printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)np->rx_ring[i].status); - printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring); + printk(KERN_DEBUG" Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %8.8x", np->tx_ring[i].status); printk("\n"); @@ -1520,7 +1520,7 @@ static int netdev_close(struct net_device *dev) printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n", i, np->tx_ring[i].length, np->tx_ring[i].status, np->tx_ring[i].buffer1); - printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", + printk(KERN_DEBUG " Rx ring %8.8x:\n", (int)np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", diff --git a/drivers/net/wan/hd64570.c b/drivers/net/wan/hd64570.c index 223238de475cd..1ea1ef6c3b962 100644 --- a/drivers/net/wan/hd64570.c +++ b/drivers/net/wan/hd64570.c @@ -584,8 +584,9 @@ static void sca_dump_rings(struct net_device *dev) sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + printk(KERN_CONT "\n"); - printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " "last=%u %sactive", sca_inw(get_dmac_tx(port) + CDAL, card), sca_inw(get_dmac_tx(port) + EDAL, card), diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c index 497b003d72392..f099c34a3ae24 100644 --- a/drivers/net/wan/hd64572.c +++ b/drivers/net/wan/hd64572.c @@ -529,8 +529,9 @@ static void sca_dump_rings(struct net_device *dev) sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in"); for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++) printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat))); + printk(KERN_CONT "\n"); - printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " + printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u " "last=%u %sactive", sca_inl(get_dmac_tx(port) + CDAL, card), sca_inl(get_dmac_tx(port) + EDAL, card), diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 3fb9dbc88a1aa..d14e95a08d668 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -326,11 +326,9 @@ sbni_pci_probe( struct net_device *dev ) } if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs) - printk( KERN_WARNING " WARNING: The PCI BIOS assigned " - "this PCI card to IRQ %d, which is unlikely " - "to work!.\n" - KERN_WARNING " You should use the PCI BIOS " - "setup to assign a valid IRQ line.\n", + printk( KERN_WARNING + " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n" + " You should use the PCI BIOS setup to assign a valid IRQ line.\n", pci_irq_line ); /* avoiding re-enable dual adapters */ diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index b10b0383dfa5e..698b11b1cadbb 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2427,11 +2427,10 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) #ifdef PCMCIA_DEBUG if (pc_debug > 3) { - int i; - printk(KERN_DEBUG "skb->data before untranslate"); - for (i = 0; i < 64; i++) - printk("%02x ", skb->data[i]); - printk("\n" KERN_DEBUG + print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ", + DUMP_PREFIX_NONE, 16, 1, + skb->data, 64, true); + printk(KERN_DEBUG "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, psnap->org[0], psnap->org[1], psnap->org[2]); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 6af706408ac08..c6d300666ad8b 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3556,17 +3556,8 @@ wv_82593_config(struct net_device * dev) cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ #ifdef DEBUG_I82593_SHOW - { - u_char *c = (u_char *) &cfblk; - int i; - printk(KERN_DEBUG "wavelan_cs: config block:"); - for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++) - { - if((i % 16) == 0) printk("\n" KERN_DEBUG); - printk("%02x ", *c); - } - printk("\n"); - } + print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE, + 16, 1, &cfblk, sizeof(struct i82593_conf_block), false); #endif /* Copy the config block to the i82593 */ diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 3c7a5053f1da7..a07580138e810 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -109,7 +109,7 @@ static int gx_fix; /* These identify the driver base version and may not be removed. */ static const char version[] __devinitconst = KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n" - KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; + " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); @@ -700,12 +700,15 @@ static void yellowfin_tx_timeout(struct net_device *dev) int i; printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", yp->rx_ring[i].result_status); - printk("\n"KERN_WARNING" Tx ring %p: ", yp->tx_ring); + printk(KERN_CONT " %8.8x", + yp->rx_ring[i].result_status); + printk(KERN_CONT "\n"); + printk(KERN_WARNING" Tx ring %p: ", yp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs, - yp->tx_ring[i].result_status); - printk("\n"); + printk(KERN_CONT " %4.4x /%8.8x", + yp->tx_status[i].tx_errs, + yp->tx_ring[i].result_status); + printk(KERN_CONT "\n"); } /* If the hardware is found to hang regularly, we will update the code @@ -1216,20 +1219,20 @@ static int yellowfin_close(struct net_device *dev) #if defined(__i386__) if (yellowfin_debug > 2) { - printk("\n"KERN_DEBUG" Tx ring at %8.8llx:\n", + printk(KERN_DEBUG" Tx ring at %8.8llx:\n", (unsigned long long)yp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE*2; i++) - printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", + printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); for (i = 0; i < TX_RING_SIZE; i++) - printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n", + printk(KERN_DEBUG " #%d status %4.4x %4.4x %4.4x %4.4x.\n", i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); - printk("\n"KERN_DEBUG " Rx ring %8.8llx:\n", + printk(KERN_DEBUG " Rx ring %8.8llx:\n", (unsigned long long)yp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index c709ecc2b7f71..0be1d50645ab0 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -101,7 +101,7 @@ static int configure_memory(const unsigned char *buf, printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(mem_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -191,7 +191,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end); result = request_resource(io_parent, res); if (result < 0) { - printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); + printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n"); return result; } } @@ -224,7 +224,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_BYTE: s=1; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outb((inb(get_16(buf+len+1) & get_8(buf+len+3)) | get_8(buf+len+4)), get_16(buf+len+1)); @@ -249,7 +249,7 @@ static int configure_port_init(const unsigned char *buf) case HPEE_PORT_INIT_WIDTH_DWORD: s=4; if (c & HPEE_PORT_INIT_MASK) { - printk("\n" KERN_WARNING "port_init: unverified mask attribute\n"); + printk(KERN_WARNING "port_init: unverified mask attribute\n"); outl((inl(get_16(buf+len+1) & get_32(buf+len+3)) | get_32(buf+len+7)), get_16(buf+len+1)); @@ -259,7 +259,7 @@ static int configure_port_init(const unsigned char *buf) break; default: - printk("\n" KERN_ERR "Invalid port init word %02x\n", c); + printk(KERN_ERR "Invalid port init word %02x\n", c); return 0; } @@ -297,7 +297,7 @@ static int configure_type_string(const unsigned char *buf) /* just skip past the type field */ len = get_8(buf); if (len > 80) { - printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); + printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len); } return 1+len; @@ -398,7 +398,7 @@ static int parse_slot_config(int slot, } if (p0 + function_len < pos) { - printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match " + printk(KERN_ERR "eisa_enumerator: function %d length mis-match " "got %d, expected %d\n", num_func, pos-p0, function_len); res=-1; diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 9ad97ea836e8a..8eb04230fec7a 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -472,7 +472,8 @@ static int __init init_tcic(void) init_timer(&poll_timer); /* Build interrupt mask */ - printk(", %d sockets\n" KERN_INFO " irq list (", sockets); + printk(KERN_CONT ", %d sockets\n", sockets); + printk(KERN_INFO " irq list ("); if (irq_list_count == 0) mask = irq_mask; else diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0471f88004836..4240b05aef6d1 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2826,8 +2826,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd) */ local_irq_restore(flags); - printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" - KERN_INFO " before abortion\n", HOSTNO); + printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); /* Maybe it is sufficient just to release the ST-DMA lock... (if * possible at all) At least, we should check if the lock could be diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index b12ad7c7c6736..18735b39b3d39 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -75,8 +75,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd * int i; printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); for (i = 0; i < cmd->cmd_len; ++i) - printk(" %.2x", cmd->cmnd[i]); - printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + printk(KERN_CONT " %.2x", cmd->cmnd[i]); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd)); } #endif diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ef142fd47a834..4d6f2fe1cfe99 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -619,7 +619,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (strcmp(current->comm, cmd) && printk_ratelimit()) { printk(KERN_WARNING "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--" - "guessing data in;\n" KERN_WARNING " " + "guessing data in;\n " "program %s not setting count and/or reply_len properly\n", old_hdr.reply_len - (int)SZ_SG_HEADER, input_size, (unsigned int) cmnd[0], diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index bcaba86060abe..75da6e58ce550 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2860,8 +2860,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) */ local_irq_restore(flags); - printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" - KERN_INFO " before abortion\n", HOSTNO); + printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); return SCSI_ABORT_NOT_RUNNING; } diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 6160e03f410ce..e7108e75653da 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -60,11 +60,12 @@ struct serial_private { static void moan_device(const char *str, struct pci_dev *dev) { - printk(KERN_WARNING "%s: %s\n" - KERN_WARNING "Please send the output of lspci -vv, this\n" - KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" - KERN_WARNING "manufacturer and name of serial board or\n" - KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n", + printk(KERN_WARNING + "%s: %s\n" + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" + "modem board to rmk+serial@arm.linux.org.uk.\n", pci_name(dev), str, dev->vendor, dev->device, dev->subsystem_vendor, dev->subsystem_device); } diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbfadbac67e88..131030f693c76 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) ssb_printk("."); err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); if (err) { - ssb_printk("\n" KERN_NOTICE PFX + ssb_printk(KERN_NOTICE PFX "Failed to write to SPROM.\n"); failed = 1; break; @@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) } err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); if (err) { - ssb_printk("\n" KERN_NOTICE PFX + ssb_printk(KERN_NOTICE PFX "Could not disable SPROM write access.\n"); failed = 1; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ce3f453f02ef5..95ccfa0b9fc52 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -648,7 +648,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) struct urb *urb; int length; unsigned long flags; - char buffer[4]; /* Any root hubs with > 31 ports? */ + char buffer[6]; /* Any root hubs with > 31 ports? */ if (unlikely(!hcd->rh_registered)) return; diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index fb8163d181abb..a21efcd10b787 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -226,9 +226,10 @@ static int clcdfb_set_par(struct fb_info *info) clcdfb_enable(fb, regs.cntl); #ifdef DEBUG - printk(KERN_INFO "CLCD: Registers set to\n" - KERN_INFO " %08x %08x %08x %08x\n" - KERN_INFO " %08x %08x %08x %08x\n", + printk(KERN_INFO + "CLCD: Registers set to\n" + " %08x %08x %08x %08x\n" + " %08x %08x %08x %08x\n", readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 0ce3b0a897980..a74e5da17aa07 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -454,9 +454,9 @@ static void DAC1064_restore_2(WPMINFO2) { dprintk(KERN_DEBUG "DAC1064regs "); for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); - if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); + if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); } - dprintk("\n" KERN_DEBUG "DAC1064clk "); + dprintk(KERN_DEBUG "DAC1064clk "); for (i = 0; i < 6; i++) dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); dprintk("\n"); diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 13524821e242c..4e825112a6017 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -651,9 +651,9 @@ static void Ti3026_restore(WPMINFO2) { dprintk(KERN_DEBUG "3026DACregs "); for (i = 0; i < 21; i++) { dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); - if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); + if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); } - dprintk("\n" KERN_DEBUG "DACclk "); + dprintk(KERN_DEBUG "DACclk "); for (i = 0; i < 6; i++) dprintk("C%02X=%02X ", i, hw->DACclk[i]); dprintk("\n"); diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index eec9dcb7f5997..6120f0c526fe0 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1115,10 +1115,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) if the device name contains the string "DX" and tell the user how to reconfigure the card. */ if (strstr(sti->outptr.dev_name, "DX")) { - printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " - "support '%s' in double-buffer mode.\n" - KERN_WARNING "WARNING: Please disable the double-buffer mode " - "in IPL menu (the PARISC-BIOS).\n", + printk(KERN_WARNING +"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" +"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", sti->outptr.dev_name); goto out_err0; } diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a0244740b75a4..b47679be118a5 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -270,19 +270,21 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, D2({ int i=0; struct jffs2_raw_node_ref *this; - printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); + printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n"); this = ic->nodes; + printk(KERN_DEBUG); while(this) { - printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); + printk(KERN_CONT "0x%08x(%d)->", + ref_offset(this), ref_flags(this)); if (++i == 5) { - printk("\n" KERN_DEBUG); + printk(KERN_DEBUG); i=0; } this = this->next_in_ino; } - printk("\n"); + printk(KERN_CONT "\n"); }); switch (ic->class) { diff --git a/kernel/module.c b/kernel/module.c index 38928fcaff2bc..0a049837008e6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2451,9 +2451,9 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, return ret; } if (ret > 0) { - printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, " - "it should follow 0/-E convention\n" - KERN_WARNING "%s: loading module anyway...\n", + printk(KERN_WARNING +"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" +"%s: loading module anyway...\n", __func__, mod->name, ret, __func__); dump_stack(); diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index e617acaf10e33..61b8ab39800ff 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -644,7 +644,7 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm * int err; int capture=1; - /* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */ + /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */ emu->p16v_device_offset = device; if (rpcm) *rpcm = NULL; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index dd1ab6177840b..9efd27f6b52f0 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -296,9 +296,10 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, struct snd_usX2Y_substream *subs, struct urb *urb) { - snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" - KERN_ERR "Most propably some urb of usb-frame %i is still missing.\n" - KERN_ERR "Cause could be too long delays in usb-hcd interrupt handling.\n", + snd_printk(KERN_ERR +"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" +"Most propably some urb of usb-frame %i is still missing.\n" +"Cause could be too long delays in usb-hcd interrupt handling.\n", usb_get_current_frame_number(usX2Y->chip.dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); -- GitLab From 44b572809581d5a10dbe35aa6bf689f32b9c5ad6 Mon Sep 17 00:00:00 2001 From: Yinghai Lu <yinghai@kernel.org> Date: Wed, 8 Jul 2009 09:50:19 -0700 Subject: [PATCH 0860/1002] x86: don't clear nodes_states[N_NORMAL_MEMORY] when numa is not compiled in Alex found that specjbb2005 still can not run with hugepages on an x86-64 machine. This only happens when numa is not compiled in. The root cause: node_set_state will not set it back for us in that case, so don't clear that when numa is not select in config [ v2: use node_clear_state instead ] Reported-and-Tested-by: Alex Shi <alex.shi@intel.com> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Reviewed-by: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/x86/mm/init_64.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index b177652251a43..6176fe8f29e01 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -598,8 +598,15 @@ void __init paging_init(void) sparse_memory_present_with_active_regions(MAX_NUMNODES); sparse_init(); - /* clear the default setting with node 0 */ - nodes_clear(node_states[N_NORMAL_MEMORY]); + + /* + * clear the default setting with node 0 + * note: don't use nodes_clear here, that is really clearing when + * numa support is not compiled in, and later node_set_state + * will not set it back. + */ + node_clear_state(0, N_NORMAL_MEMORY); + free_area_init_nodes(max_zone_pfns); } -- GitLab From 19e588e7d156cc4415585edd8c27c3075f62eaf8 Mon Sep 17 00:00:00 2001 From: Alexander Duyck <alexander.h.duyck@intel.com> Date: Tue, 7 Jul 2009 13:01:55 +0000 Subject: [PATCH 0861/1002] igb: set lan id prior to configuring phy The igb driver was defaulting to using the lock for pci-e function 0 for all of the phys due to the fact that the lan id was not being set prior to initialization. This change makes it so that the function id is set prior to checking for the phy id. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/igb/e1000_82575.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index efd9be214885c..ac28dd5a4fd13 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -190,6 +190,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) phy->ops.write_reg = igb_write_phy_reg_igp; } + /* set lan id */ + hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> + E1000_STATUS_FUNC_SHIFT; + /* Set phy->phy_addr and phy->id. */ ret_val = igb_get_phy_id_82575(hw); if (ret_val) -- GitLab From 64c8165b44a91c09b19afb4110610ed242286639 Mon Sep 17 00:00:00 2001 From: Pablo Bitton <pablo.bitton@gmail.com> Date: Tue, 7 Jul 2009 19:11:10 -0700 Subject: [PATCH 0862/1002] davinci_emac: fix kernel oops when changing MAC address while interface is down Check that network interface is running before changing its MAC address. Otherwise, rxch is accessed when it's NULL - causing a kernel oops. Moreover, check that the new MAC address is valid. Signed-off-by: Pablo Bitton <pablo.bitton@gmail.com> Signed-off-by: Chaithrika U S <chaithrika@ti.com> Tested-by: Chaithrika U S <chaithrika@ti.com> [tested on DM6467 EVM] Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/davinci_emac.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2df8fb0af701a..12fd446f98950 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1820,11 +1820,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; + if (!is_valid_ether_addr(sa->sa_data)) + return -EINVAL; + /* Store mac addr in priv and rx channel and set it in EMAC hw */ memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + + /* If the interface is down - rxch is NULL. */ + /* MAC address is configured only after the interface is enabled. */ + if (netif_running(ndev)) { + memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + } if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n", -- GitLab From 345aa031207d02d7438c1aa96ed9315911ecd745 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski <jarkao2@gmail.com> Date: Tue, 7 Jul 2009 19:39:16 -0700 Subject: [PATCH 0863/1002] ipv4: Fix fib_trie rebalancing, part 4 (root thresholds) Pawel Staszewski wrote: <blockquote> Some time ago i report this: http://bugzilla.kernel.org/show_bug.cgi?id=6648 and now with 2.6.29 / 2.6.29.1 / 2.6.29.3 and 2.6.30 it back dmesg output: oprofile: using NMI interrupt. Fix inflate_threshold_root. Now=15 size=11 bits ... Fix inflate_threshold_root. Now=15 size=11 bits cat /proc/net/fib_triestat Basic info: size of leaf: 40 bytes, size of tnode: 56 bytes. Main: Aver depth: 2.28 Max depth: 6 Leaves: 276539 Prefixes: 289922 Internal nodes: 66762 1: 35046 2: 13824 3: 9508 4: 4897 5: 2331 6: 1149 7: 5 9: 1 18: 1 Pointers: 691228 Null ptrs: 347928 Total size: 35709 kB </blockquote> It seems, the current threshold for root resizing is too aggressive, and it causes misleading warnings during big updates, but it might be also responsible for memory problems, especially with non-preempt configs, when RCU freeing is delayed long after call_rcu. It should be also mentioned that because of non-atomic changes during resizing/rebalancing the current lookup algorithm can miss valid leaves so it's additional argument to shorten these activities even at a cost of a minimally longer searching. This patch restores values before the patch "[IPV4]: fib_trie root node settings", commit: 965ffea43d4ebe8cd7b9fee78d651268dd7d23c5 from v2.6.22. Pawel's report: <blockquote> I dont see any big change of (cpu load or faster/slower routing/propagating routes from bgpd or something else) - in avg there is from 2% to 3% more of CPU load i dont know why but it is - i change from "preempt" to "no preempt" 3 times and check this my "mpstat -P ALL 1 30" always avg cpu load was from 2 to 3% more compared to "no preempt" [...] cat /proc/net/fib_triestat Basic info: size of leaf: 20 bytes, size of tnode: 36 bytes. Main: Aver depth: 2.44 Max depth: 6 Leaves: 277814 Prefixes: 291306 Internal nodes: 66420 1: 32737 2: 14850 3: 10332 4: 4871 5: 2313 6: 942 7: 371 8: 3 17: 1 Pointers: 599098 Null ptrs: 254865 Total size: 18067 kB </blockquote> According to this and other similar reports average depth is slightly increased (~0.2), and root nodes are shorter (log 17 vs. 18), but there is no visible performance decrease. So, until memory handling is improved or added parameters for changing this individually, this patch resets to safer defaults. Reported-by: Pawel Staszewski <pstaszewski@itcare.pl> Reported-by: Jorge Boncompte [DTI2] <jorge@dti2.net> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> Tested-by: Pawel Staszewski <pstaszewski@itcare.pl> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/ipv4/fib_trie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 00a54b246dfed..63c2fa7b68c4b 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -316,8 +316,8 @@ static inline void check_tnode(const struct tnode *tn) static const int halve_threshold = 25; static const int inflate_threshold = 50; -static const int halve_threshold_root = 8; -static const int inflate_threshold_root = 15; +static const int halve_threshold_root = 15; +static const int inflate_threshold_root = 25; static void __alias_free_mem(struct rcu_head *head) -- GitLab From 35976d4d557c5017c2180a083e8bd970cf73f3d5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli <florian@openwrt.org> Date: Wed, 8 Jul 2009 03:05:14 +0000 Subject: [PATCH 0864/1002] r6040: restore MIER register correctly when IRQ line is shared When the r6040 device IRQ line is shared we will enter the driver interrupt service routine, mask off the device interrupt enable register (MIER) and return with IRQ_NONE, we would then leave the device with interrupts disabled, this patch fixes that issue. Reported-by: Steve Holland <sdh4@iastate.edu> Signed-off-by: Joe Chou <joe.chou@rdc.com.tw> Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/r6040.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index ed63d23a64523..70aac35dc2dbb 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -704,8 +704,11 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) /* Read MISR status and clear */ status = ioread16(ioaddr + MISR); - if (status == 0x0000 || status == 0xffff) + if (status == 0x0000 || status == 0xffff) { + /* Restore RDC MAC interrupt */ + iowrite16(misr, ioaddr + MIER); return IRQ_NONE; + } /* RX interrupt request */ if (status & RX_INTS) { -- GitLab From c3b85423072c0739d76b7c54080d3f3ccc5dad4d Mon Sep 17 00:00:00 2001 From: Florian Fainelli <florian@openwrt.org> Date: Wed, 8 Jul 2009 03:05:48 +0000 Subject: [PATCH 0865/1002] r6040: bump driver version to 0.24 and date to 08 July 2009 Signed-off-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/r6040.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 70aac35dc2dbb..961b5397a531e 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include <asm/processor.h> #define DRV_NAME "r6040" -#define DRV_VERSION "0.23" -#define DRV_RELDATE "05May2009" +#define DRV_VERSION "0.24" +#define DRV_RELDATE "08Jul2009" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ -- GitLab From b4b223cdd5981f776491134faa7bc4ac342b44d4 Mon Sep 17 00:00:00 2001 From: Pascal Terjan <pterjan@mandriva.com> Date: Thu, 18 Jun 2009 17:54:03 +0200 Subject: [PATCH 0866/1002] zd1211rw: 07b8:6001 is a ZD1211B On a shuttle machine here we got 07b8:6001 device, handled by zd1211rw, which does not work. Scanning is OK but association does not work, we get "direct probe to AP xxx timed out" It appears that this simple patch makes the device work perfectly. This id was already there in initial import of the driver so I don't know if it has ever been working as ZD1211 (which would mean they changed it and kept the id :( ). Signed-off-by: Pascal Terjan <pterjan@mandriva.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/zd1211rw/zd_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 14a19baff2144..9b31afc5a0c7c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -38,7 +38,6 @@ static struct usb_device_id usb_ids[] = { /* ZD1211 */ { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, @@ -87,6 +86,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, -- GitLab From 8b339d05805fb91cc0b5179af5b4d05d9f8b949c Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung <hintak.leung@gmail.com> Date: Fri, 26 Jun 2009 05:28:15 +0100 Subject: [PATCH 0867/1002] zd1211rw: adding SONY IFU-WLM2 (054c:0257) as a zd1211b device Yevgen Kotikov reported success on the sourceforge zd1211-devs list with the following details: Brand/retail: SONY IFU-WLM2 USB-IDs: Vendor: 0x054C Device: 0x0257 chip ID: zd1211b chip 054c:0257 v4802 high 00-0b-6b AL2230_RF pa0 ----- FCC ID: unknown Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net> Tested-by: Yevgen Kotikov <yevgen.kotikov@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 9b31afc5a0c7c..0e6e44689cc61 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -60,6 +60,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ + { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, -- GitLab From cff782cd94df7adea84af6aa9516c8088f7ea950 Mon Sep 17 00:00:00 2001 From: Clyde McPherson <ccmcphe@verizon.net> Date: Tue, 30 Jun 2009 22:39:28 -0500 Subject: [PATCH 0868/1002] b43: Add support for 4318E Added support for the Broadcom 4318E chipset on PCMCIA/CF cards. The 4318E can do 802.11A/B/G, only B and G mode are supported in b43. Signed-off-by: Clyde McPherson <ccmcphe@verizon.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/b43/pcmcia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 3cfc30307a27d..6c3a74964ab88 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -35,6 +35,7 @@ static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), + PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), PCMCIA_DEVICE_NULL, }; -- GitLab From 2fbddeb5c409c90be4706ea2beb7f1fc02100c72 Mon Sep 17 00:00:00 2001 From: Clyde McPherson <ccmcphe@verizon.net> Date: Tue, 30 Jun 2009 22:39:43 -0500 Subject: [PATCH 0869/1002] ssb: Add support for 4318E Added support for the Broadcom 4318E chipset on PCMCIA/CF cards. The 4318E can do 802.11A/B/G, only B and G mode are supported in b43. Signed-off-by: Clyde McPherson <ccmcphe@verizon.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/ssb/pcmcia.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index fbfadbac67e88..d288608d22067 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, sprom->board_rev = tuple.TupleData[1]; break; case SSB_PCMCIA_CIS_PA: - GOTO_ERROR_ON(tuple.TupleDataLen != 9, + GOTO_ERROR_ON((tuple.TupleDataLen != 9) && + (tuple.TupleDataLen != 10), "pa tpl size"); sprom->pa0b0 = tuple.TupleData[1] | ((u16)tuple.TupleData[2] << 8); @@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; break; case SSB_PCMCIA_CIS_BFLAGS: - GOTO_ERROR_ON(tuple.TupleDataLen != 3, + GOTO_ERROR_ON((tuple.TupleDataLen != 3) && + (tuple.TupleDataLen != 5), "bfl tpl size"); sprom->boardflags_lo = tuple.TupleData[1] | ((u16)tuple.TupleData[2] << 8); -- GitLab From 4ff176674e75bdee9022dded415fb805f15700ad Mon Sep 17 00:00:00 2001 From: Johannes Berg <johannes@sipsolutions.net> Date: Tue, 7 Jul 2009 03:43:02 +0200 Subject: [PATCH 0870/1002] mac80211_hwsim: avoid NULL access There's a race condition -- started can be set to true before channel is set due to the way mac80211 callbacks currently work (->start should probably pass the channel we would like to have initially). For now simply add a check to hwsim to avoid dereferencing the NULL channel pointer. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/mac80211_hwsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e789c6e9938cb..a111bda392e20 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -418,6 +418,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, continue; if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || + !data->channel || !data2->channel || data->channel->center_freq != data2->channel->center_freq || !(data->group & data2->group)) continue; -- GitLab From b9744d19e35d74f965fb94bd55f9313d3a7d9e54 Mon Sep 17 00:00:00 2001 From: Johannes Berg <johannes@sipsolutions.net> Date: Tue, 7 Jul 2009 11:10:12 +0200 Subject: [PATCH 0871/1002] mac80211: fix docbook These two functions no longer exist in mac80211, so trying to insert them generates warnings in the document. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- Documentation/DocBook/mac80211.tmpl | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index e36986663570d..f3f37f141dbdb 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -184,8 +184,6 @@ usage should require reading the full document. !Finclude/net/mac80211.h ieee80211_ctstoself_get !Finclude/net/mac80211.h ieee80211_ctstoself_duration !Finclude/net/mac80211.h ieee80211_generic_frame_duration -!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb -!Finclude/net/mac80211.h ieee80211_hdrlen !Finclude/net/mac80211.h ieee80211_wake_queue !Finclude/net/mac80211.h ieee80211_stop_queue !Finclude/net/mac80211.h ieee80211_wake_queues -- GitLab From 804ef71ee183121de5e9bca1d70d114c97300e17 Mon Sep 17 00:00:00 2001 From: Jay Sternberg <jay.e.sternberg@intel.com> Date: Tue, 7 Jul 2009 11:18:46 -0700 Subject: [PATCH 0872/1002] Atheros Kconfig needs to be dependent on WLAN_80211 Atheros top level menu needs a "depends WLAN_80211" to properly indent within menuconfig and xconfig interfaces. This is purely a visual issue but it effects all subsequent drivers. The issue is the top level menu does not include a dependency on WLAN_80211 so within the tree structure, Atheros is at the same level as WLAN_80211 but when WLAN_80211 collapsed, the menu disappears along with all subsequent drives, so it is really a subordinate. Signed-off-by: Jay Sternberg <jay.e.sternberg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/ath/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index d26e7b4853156..eb0337c49546b 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -1,5 +1,6 @@ config ATH_COMMON tristate "Atheros Wireless Cards" + depends on WLAN_80211 depends on ATH5K || ATH9K || AR9170_USB source "drivers/net/wireless/ath/ath5k/Kconfig" -- GitLab From 47ab3840a389ff1b9959734995123e5bc94c3443 Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Wed, 8 Jul 2009 08:33:02 -0500 Subject: [PATCH 0873/1002] p54: tx refused but queue active In the mainline kernel, p54usb will fail because the TX queue length can become < 0. This problem has been reported as Bugzilla #13725. The failure is expressed by the following message in the logs: WARNING: at net/mac80211/tx.c:1325 ieee80211_tx+0x23c/0x298 [mac80211]() Hardware name: HP Pavilion dv2700 Notebook PC tx refused but queue active This problem has been recently observed in the wireless-testing tree, where a full solution is being tested. That fix is too invasive for 2.6.31-rcX, but the simple change supplied here will prevent the failure. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/p54/p54common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 48d81d98e12d4..22ca122bd798c 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -912,13 +912,14 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) } __skb_unlink(entry, &priv->tx_queue); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); frame_len = entry->len; entry_hdr = (struct p54_hdr *) entry->data; entry_data = (struct p54_tx_data *) entry_hdr->data; - priv->tx_stats[entry_data->hw_queue].len--; + if (priv->tx_stats[entry_data->hw_queue].len) + priv->tx_stats[entry_data->hw_queue].len--; priv->stats.dot11ACKFailureCount += payload->tries - 1; + spin_unlock_irqrestore(&priv->tx_queue.lock, flags); /* * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are -- GitLab From 1ce822fa04fd6878f079461a4b8affe4bb5ec27b Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput <jaswinder@kernel.org> Date: Wed, 8 Jul 2009 21:25:54 +0530 Subject: [PATCH 0874/1002] includecheck fix: include/linux, rfkill.h fix the following 'make includecheck' warning: include/linux/rfkill.h: linux/types.h is included more than once. Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- include/linux/rfkill.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index e73e2429a1b1c..2ce29831feb61 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h @@ -99,7 +99,6 @@ enum rfkill_user_states { #undef RFKILL_STATE_UNBLOCKED #undef RFKILL_STATE_HARD_BLOCKED -#include <linux/types.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/mutex.h> -- GitLab From b5daa70a4a55a807e893fe7f94289c61c50a6e5f Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Wed, 8 Jul 2009 21:59:17 +0200 Subject: [PATCH 0875/1002] fsl-diu-fb: fix regression with uninitalized fb_info->mm_lock mutex Remove call to the fsl_diu_set_par before the register_framebuffer(). This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Tested-by: "Kai Jiang" <b18973@freescale.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/fsl-diu-fb.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0bf2190928d0e..72d68b3dc478e 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1223,12 +1223,6 @@ static int __devinit install_fb(struct fb_info *info) return -EINVAL; } - if (fsl_diu_set_par(info)) { - printk(KERN_ERR "fb_set_par failed"); - fb_dealloc_cmap(&info->cmap); - return -EINVAL; - } - if (register_framebuffer(info) < 0) { printk(KERN_ERR "register_framebuffer failed"); unmap_video_memory(info); -- GitLab From 1d01e83557105e7b3bf1623ad2b814d55e1c2990 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Wed, 8 Jul 2009 22:26:16 +0200 Subject: [PATCH 0876/1002] atmel_lcdfb: fix regression with uninitalized fb_info->mm_lock mutex Remove not needed locking of the fb_info->mm_lock mutex before a frambuffer is registered. This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/atmel_lcdfb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index cb88394ba9952..da05f0801bb75 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -261,6 +261,9 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) /** * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory * @sinfo: the frame buffer to allocate memory for + * + * This function is called only from the atmel_lcdfb_probe() + * so no locking by fb_info->mm_lock around smem_len setting is needed. */ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) { @@ -270,9 +273,7 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) smem_len = (var->xres_virtual * var->yres_virtual * ((var->bits_per_pixel + 7) / 8)); - mutex_lock(&info->mm_lock); info->fix.smem_len = max(smem_len, sinfo->smem_len); - mutex_unlock(&info->mm_lock); info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); -- GitLab From 5ddf1e0ff00fd808c048d0b920784828276cc516 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Sun, 5 Jul 2009 11:01:02 -0400 Subject: [PATCH 0877/1002] cifs: fix regression with O_EXCL creates and optimize away lookup cifs: fix regression with O_EXCL creates and optimize away lookup Signed-off-by: Jeff Layton <jlayton@redhat.com> Tested-by: Shirish Pargaonkar <shirishp@gmail.com> CC: Stable Kernel <stable@kernel.org> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/dir.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index a40054faed7f6..ff55fc6932cb8 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -643,6 +643,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } } + /* + * O_EXCL: optimize away the lookup, but don't hash the dentry. Let + * the VFS handle the create. + */ + if (nd->flags & LOOKUP_EXCL) { + d_instantiate(direntry, NULL); + return 0; + } + /* can not grab the rename sem here since it would deadlock in the cases (beginning of sys_rename itself) in which we already have the sb rename sem */ -- GitLab From 5e1596f75395e7a402e1059c518e633d2732dcf8 Mon Sep 17 00:00:00 2001 From: Dave Jones <davej@redhat.com> Date: Wed, 8 Jul 2009 16:14:23 -0400 Subject: [PATCH 0878/1002] [CPUFREQ] Fix compile failure in cpufreq.c managed_policy is out of scope for the non-smp case. Declare it locally where used (twice) Signed-off-by: Dave Jones <davej@redhat.com> --- drivers/cpufreq/cpufreq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c668ac855f71c..b90eda8b34409 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -776,9 +776,6 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) struct sys_device *cpu_sys_dev; unsigned long flags; unsigned int j; -#ifdef CONFIG_SMP - struct cpufreq_policy *managed_policy; -#endif if (cpu_is_offline(cpu)) return 0; @@ -854,6 +851,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) #endif for_each_cpu(j, policy->cpus) { + struct cpufreq_policy *managed_policy; + if (cpu == j) continue; @@ -932,6 +931,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) /* symlink affected CPUs */ for_each_cpu(j, policy->cpus) { + struct cpufreq_policy *managed_policy; + if (j == cpu) continue; if (!cpu_online(j)) -- GitLab From 2e3167308048ca6c810733384d8289082f7e4ec1 Mon Sep 17 00:00:00 2001 From: Roland Dreier <rdreier@cisco.com> Date: Wed, 8 Jul 2009 17:05:32 -0700 Subject: [PATCH 0879/1002] fealnx: Fix build breakage -- PR_CONT should be KERN_CONT Commit ad361c98 ("Remove multiple KERN_ prefixes from printk formats") broke the build for fealnx because it added some "printk(PR_CONT ..." calls, when PR_CONT doesn't exist; it should be "printk(KERN_CONT ..." Signed-off-by: Roland Dreier <rolandd@cisco.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/net/fealnx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 053fb49820b9c..48385c42ab574 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1216,13 +1216,13 @@ static void fealnx_tx_timeout(struct net_device *dev) { printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(PR_CONT " %8.8x", + printk(KERN_CONT " %8.8x", (unsigned int) np->rx_ring[i].status); printk(KERN_CONT "\n"); printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(PR_CONT " %4.4x", np->tx_ring[i].status); - printk(PR_CONT "\n"); + printk(KERN_CONT " %4.4x", np->tx_ring[i].status); + printk(KERN_CONT "\n"); } spin_lock_irqsave(&np->lock, flags); -- GitLab From 1b614fb9a00e97b1eab54d4e442d405229c059dd Mon Sep 17 00:00:00 2001 From: Anton Vorontsov <avorontsov@ru.mvista.com> Date: Wed, 8 Jul 2009 20:09:44 -0700 Subject: [PATCH 0880/1002] netpoll: Fix carrier detection for drivers that are using phylib Using early netconsole and gianfar driver this error pops up: netconsole: timeout waiting for carrier It appears that net/core/netpoll.c:netpoll_setup() is using cond_resched() in a loop waiting for a carrier. The thing is that cond_resched() is a no-op when system_state != SYSTEM_RUNNING, and so drivers/net/phy/phy.c's state_queue is never scheduled, therefore link detection doesn't work. I belive that the main problem is in cond_resched()[1], but despite how the cond_resched() story ends, it might be a good idea to call msleep(1) instead of cond_resched(), as suggested by Andrew Morton. [1] http://lkml.org/lkml/2009/7/7/463 Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9675f312830dd..df30feb2fc725 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -740,7 +740,7 @@ int netpoll_setup(struct netpoll *np) np->name); break; } - cond_resched(); + msleep(1); } /* If carrier appears to come up instantly, we don't -- GitLab From 086b3640c10ab448a6993c4bae1508f496f530c4 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 29 Jun 2009 16:25:33 +0300 Subject: [PATCH 0881/1002] UBIFS: dump a little more in case of corruptions In case of corruptions, dump 8192 bytes instead of 4096. The largest node is 4096+ bytes, so it is better to see a node boundary, which is not always possible when only 4096 bytes are printed. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Adrian Hunter <Adrian.Hunter@nokia.com> --- fs/ubifs/scan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 0ed82479b44b4..165c14ba1a46d 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -238,12 +238,12 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, { int len; - ubifs_err("corrupted data at LEB %d:%d", lnum, offs); + ubifs_err("corruption at LEB %d:%d", lnum, offs); if (dbg_failure_mode) return; len = c->leb_size - offs; - if (len > 4096) - len = 4096; + if (len > 8192) + len = 8192; dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); } -- GitLab From ed43f2f06cc1cec7ec2dc235c908530bc8c796eb Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 29 Jun 2009 17:59:23 +0300 Subject: [PATCH 0882/1002] UBIFS: small amendments in the LEB scanning code This patch fixes few minor things I've spotted while going through code: 1. Better document return codes 2. If 'ubifs_scan_a_node()' returns some thing we do not expect, treat this as an error. 3. Try to do recovery only when 'ubifs_scan()' returns %-EUCLEAN, not on any error. 4. If empty space starts at a non-aligned address, print a message. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Adrian Hunter <Adrian.Hunter@nokia.com> --- fs/ubifs/recovery.c | 7 ++++--- fs/ubifs/replay.c | 7 ++++--- fs/ubifs/scan.c | 14 +++++++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 805605250f128..093a1ecb700f2 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -543,8 +543,8 @@ static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs) * * This function does a scan of a LEB, but caters for errors that might have * been caused by the unclean unmount from which we are attempting to recover. - * - * This function returns %0 on success and a negative error code on failure. + * Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is + * found, and a negative error code in case of failure. */ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf, int grouped) @@ -643,7 +643,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, goto corrupted; default: dbg_err("unknown"); - goto corrupted; + err = -EINVAL; + goto error; } } diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 769be42f39d6b..2970500f32dfb 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -837,9 +837,10 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) dbg_mnt("replay log LEB %d:%d", lnum, offs); sleb = ubifs_scan(c, lnum, offs, sbuf); - if (IS_ERR(sleb)) { - if (c->need_recovery) - sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); + if (IS_ERR(sleb) ) { + if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery) + return PTR_ERR(sleb); + sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); if (IS_ERR(sleb)) return PTR_ERR(sleb); } diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 165c14ba1a46d..892ebfee4fe53 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -256,7 +256,9 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, * @sbuf: scan buffer (must be c->leb_size) * * This function scans LEB number @lnum and returns complete information about - * its contents. Returns an error code in case of failure. + * its contents. Returns the scaned information in case of success and, + * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case + * of failure. */ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, int offs, void *sbuf) @@ -279,7 +281,6 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, cond_resched(); ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); - if (ret > 0) { /* Padding bytes or a valid padding node */ offs += ret; @@ -304,7 +305,8 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, goto corrupted; default: dbg_err("unknown"); - goto corrupted; + err = -EINVAL; + goto error; } err = ubifs_add_snod(c, sleb, buf, offs); @@ -317,8 +319,10 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, len -= node_len; } - if (offs % c->min_io_size) - goto corrupted; + if (offs % c->min_io_size) { + ubifs_err("empty space starts at non-aligned offset %d", offs); + goto corrupted;; + } ubifs_end_scan(c, sleb, lnum, offs); -- GitLab From 431102fed3effe4e4e19678830ddab7f05c34bf9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 29 Jun 2009 18:58:34 +0300 Subject: [PATCH 0883/1002] UBIFS: clean up free space checking recovery.c has 'is_empty()' helper and it is better to use this helper instead of re-implementing it in several places. This patch does this and removes some amount of unneeded code. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Adrian Hunter <Adrian.Hunter@nokia.com> --- fs/ubifs/recovery.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 093a1ecb700f2..fe7af9f676b06 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -357,11 +357,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs) empty_offs = ALIGN(offs + 1, c->min_io_size); check_len = c->leb_size - empty_offs; p = buf + empty_offs - offs; - - for (; check_len > 0; check_len--) - if (*p++ != 0xff) - return 0; - return 1; + return is_empty(p, check_len); } /** @@ -814,7 +810,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, static int recover_head(const struct ubifs_info *c, int lnum, int offs, void *sbuf) { - int len, err, need_clean = 0; + int len, err; if (c->min_io_size > 1) len = c->min_io_size; @@ -828,19 +824,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs, /* Read at the head location and check it is empty flash */ err = ubi_read(c->ubi, lnum, sbuf, offs, len); - if (err) - need_clean = 1; - else { - uint8_t *p = sbuf; - - while (len--) - if (*p++ != 0xff) { - need_clean = 1; - break; - } - } - - if (need_clean) { + if (err || !is_empty(sbuf, len)) { dbg_rcvry("cleaning head at %d:%d", lnum, offs); if (offs == 0) return ubifs_leb_unmap(c, lnum); -- GitLab From 061125476039a9a998878468a6abe235b1cee347 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Date: Mon, 29 Jun 2009 19:27:14 +0300 Subject: [PATCH 0884/1002] UBIFS: fix corruption dump In the 'ubifs_recover_leb()' function, when we find corrupted empty space, we dump 8K starting from the offset where the last node ends. This is OK if the corrupted empty space is somewhere near that offset. But if the corruption is far at the end of the LEB, we will dump all 0xFF bytes and complitely ignore the interesting data. This is observed on a PPC ("kilauea") with NOR flash. This patch changes the behavior and teaches UBIFS to print only interesting data. I.e., now we find where corruption starts and start dumping from that offset. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Adrian Hunter <Adrian.Hunter@nokia.com> --- fs/ubifs/recovery.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index fe7af9f676b06..e5f6cf8a11553 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -52,6 +52,25 @@ static int is_empty(void *buf, int len) return 1; } +/** + * first_non_ff - find offset of the first non-0xff byte. + * @buf: buffer to search in + * @len: length of buffer + * + * This function returns offset of the first non-0xff byte in @buf or %-1 if + * the buffer contains only 0xff bytes. + */ +static int first_non_ff(void *buf, int len) +{ + uint8_t *p = buf; + int i; + + for (i = 0; i < len; i++) + if (*p++ != 0xff) + return i; + return -1; +} + /** * get_master_node - get the last valid master node allowing for corruption. * @c: UBIFS file-system description object @@ -649,8 +668,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, clean_buf(c, &buf, lnum, &offs, &len); need_clean = 1; } else { - ubifs_err("corrupt empty space at LEB %d:%d", - lnum, offs); + int corruption = first_non_ff(buf, len); + + ubifs_err("corrupt empty space LEB %d:%d, corruption " + "starts at %d", lnum, offs, corruption); + /* Make sure we dump interesting non-0xFF data */ + offs = corruption; + buf += corruption; goto corrupted; } } -- GitLab From 369693dc93533097c0ca7243affb4f3244c336e8 Mon Sep 17 00:00:00 2001 From: Paul Vojta <vojta@math.berkeley.edu> Date: Wed, 8 Jul 2009 23:57:46 -0700 Subject: [PATCH 0885/1002] ALSA: hda - fix beep tone calculation for IDT/STAC codecs In the beep tone calculation for IDT/STAC codecs, lower numbers correspond to higher frequencies and vice versa. The current code has this backwards, resulting in beep frequencies which are way too high (and sound bad on tinny laptop speakers, resulting in complaints). [Also added hz <= 0 check by tiwai] Signed-off-by: Paul Vojta <vojta@math.berkeley.edu> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/hda_beep.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 29272f2e95a07..b0275a0508701 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -50,19 +50,22 @@ static void snd_hda_generate_beep(struct work_struct *work) * The tone frequency of beep generator on IDT/STAC codecs is * defined from the 8bit tone parameter, in Hz, * freq = 48000 * (257 - tone) / 1024 - * that is from 12kHz to 93.75kHz in step of 46.875 hz + * that is from 12kHz to 93.75Hz in steps of 46.875 Hz */ static int beep_linear_tone(struct hda_beep *beep, int hz) { + if (hz <= 0) + return 0; hz *= 1000; /* fixed point */ - hz = hz - DIGBEEP_HZ_MIN; + hz = hz - DIGBEEP_HZ_MIN + + DIGBEEP_HZ_STEP / 2; /* round to nearest step */ if (hz < 0) hz = 0; /* turn off PC beep*/ else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) - hz = 0xff; + hz = 1; /* max frequency */ else { hz /= DIGBEEP_HZ_STEP; - hz++; + hz = 255 - hz; } return hz; } -- GitLab From 02239f0a4264608686cc0015d906c7b2dead89df Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Wed, 8 Jul 2009 02:00:49 +0100 Subject: [PATCH 0886/1002] [ARM] 5577/2: ep93xx: syscon locked register functions Add core functions to handle writes to the ep93xx software locked registers. There are a number of registers in the EP93xx System Controller that require a write to the software lock register before they can be updated. This patch adds a number of exported functions to the ep93xx core that handle this access. The software locked clock divider registers, VidClkDiv, MIRClkDiv, I2SClkDiv and KeyTchClkDiv would typically involve writing a specific value to the register. To support this the ep93xx_syscon_swlocked_write() function is provided. For the DeviceCfg register it's more typical to only need to set or clear a single bit. A generic ep93xx_devcfg_set_clear() function is provided to handle both operations. Two inline functions, ep93xx_devcfg_set_bits() and ep93xx_devcfg_clear_bits() are also provided to improve code readability. In addition, the remaining bits in the System Controller Device Config Register have been documented and the previously defined names shortened. All code paths that use this functionality have been updated except for arch/arm/kernel/crunch.c. That code is in a context switch path, which is not reentrant, so it is safe against itself. Cc: Lennert Buytenhek <buytenh@wantstofly.org> Cc: Matthias Kaehlcke <matthias@kaehlcke.net> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/kernel/crunch.c | 13 +++-- arch/arm/mach-ep93xx/clock.c | 24 +++++---- arch/arm/mach-ep93xx/core.c | 52 +++++++++++++++---- .../mach-ep93xx/include/mach/ep93xx-regs.h | 36 +++++++++++-- arch/arm/mach-ep93xx/include/mach/platform.h | 16 ++++++ arch/arm/mach-ep93xx/include/mach/system.h | 12 ++--- 6 files changed, 118 insertions(+), 35 deletions(-) diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c index 99995c2b23125..769abe15cf91d 100644 --- a/arch/arm/kernel/crunch.c +++ b/arch/arm/kernel/crunch.c @@ -31,7 +31,7 @@ void crunch_task_release(struct thread_info *thread) static int crunch_enabled(u32 devcfg) { - return !!(devcfg & EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); + return !!(devcfg & EP93XX_SYSCON_DEVCFG_CPENA); } static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t) @@ -56,11 +56,16 @@ static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t) break; case THREAD_NOTIFY_SWITCH: - devcfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + devcfg = __raw_readl(EP93XX_SYSCON_DEVCFG); if (crunch_enabled(devcfg) || crunch_owner == crunch_state) { - devcfg ^= EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; + /* + * We don't use ep93xx_syscon_swlocked_write() here + * because we are on the context switch path and + * preemption is already disabled. + */ + devcfg ^= EP93XX_SYSCON_DEVCFG_CPENA; __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(devcfg, EP93XX_SYSCON_DEVICE_CONFIG); + __raw_writel(devcfg, EP93XX_SYSCON_DEVCFG); } break; } diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 6c4c1633ed123..c7642acfd0224 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -50,20 +50,20 @@ static unsigned long get_uart_rate(struct clk *clk); static struct clk clk_uart1 = { .sw_locked = 1, - .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, - .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U1EN, + .enable_reg = EP93XX_SYSCON_DEVCFG, + .enable_mask = EP93XX_SYSCON_DEVCFG_U1EN, .get_rate = get_uart_rate, }; static struct clk clk_uart2 = { .sw_locked = 1, - .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, - .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U2EN, + .enable_reg = EP93XX_SYSCON_DEVCFG, + .enable_mask = EP93XX_SYSCON_DEVCFG_U2EN, .get_rate = get_uart_rate, }; static struct clk clk_uart3 = { .sw_locked = 1, - .enable_reg = EP93XX_SYSCON_DEVICE_CONFIG, - .enable_mask = EP93XX_SYSCON_DEVICE_CONFIG_U3EN, + .enable_reg = EP93XX_SYSCON_DEVCFG, + .enable_mask = EP93XX_SYSCON_DEVCFG_U3EN, .get_rate = get_uart_rate, }; static struct clk clk_pll1; @@ -160,9 +160,11 @@ int clk_enable(struct clk *clk) u32 value; value = __raw_readl(clk->enable_reg); + value |= clk->enable_mask; if (clk->sw_locked) - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(value | clk->enable_mask, clk->enable_reg); + ep93xx_syscon_swlocked_write(value, clk->enable_reg); + else + __raw_writel(value, clk->enable_reg); } return 0; @@ -175,9 +177,11 @@ void clk_disable(struct clk *clk) u32 value; value = __raw_readl(clk->enable_reg); + value &= ~clk->enable_mask; if (clk->sw_locked) - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(value & ~clk->enable_mask, clk->enable_reg); + ep93xx_syscon_swlocked_write(value, clk->enable_reg); + else + __raw_writel(value, clk->enable_reg); } } EXPORT_SYMBOL(clk_disable); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 204dc5cbd0b88..9399d3af9906e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -384,6 +384,47 @@ void __init ep93xx_init_irq(void) } +/************************************************************************* + * EP93xx System Controller Software Locked register handling + *************************************************************************/ + +/* + * syscon_swlock prevents anything else from writing to the syscon + * block while a software locked register is being written. + */ +static DEFINE_SPINLOCK(syscon_swlock); + +void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg) +{ + unsigned long flags; + + spin_lock_irqsave(&syscon_swlock, flags); + + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(val, reg); + + spin_unlock_irqrestore(&syscon_swlock, flags); +} +EXPORT_SYMBOL(ep93xx_syscon_swlocked_write); + +void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&syscon_swlock, flags); + + val = __raw_readl(EP93XX_SYSCON_DEVCFG); + val |= set_bits; + val &= ~clear_bits; + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(val, EP93XX_SYSCON_DEVCFG); + + spin_unlock_irqrestore(&syscon_swlock, flags); +} +EXPORT_SYMBOL(ep93xx_devcfg_set_clear); + + /************************************************************************* * EP93xx peripheral handling *************************************************************************/ @@ -550,15 +591,8 @@ extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) { - unsigned int v; - - /* - * Disallow access to MaverickCrunch initially. - */ - v = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); - v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); + /* Disallow access to MaverickCrunch initially */ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); ep93xx_gpio_init(); diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 49b256b3ddfc2..087d22b8f3511 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -175,11 +175,37 @@ #define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) #define EP93XX_SYSCON_CLOCK_SET1 EP93XX_SYSCON_REG(0x20) #define EP93XX_SYSCON_CLOCK_SET2 EP93XX_SYSCON_REG(0x24) -#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80) -#define EP93XX_SYSCON_DEVICE_CONFIG_U3EN (1<<24) -#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE (1<<23) -#define EP93XX_SYSCON_DEVICE_CONFIG_U2EN (1<<20) -#define EP93XX_SYSCON_DEVICE_CONFIG_U1EN (1<<18) +#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80) +#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31) +#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30) +#define EP93XX_SYSCON_DEVCFG_D0ONG (1<<29) +#define EP93XX_SYSCON_DEVCFG_IONU2 (1<<28) +#define EP93XX_SYSCON_DEVCFG_GONK (1<<27) +#define EP93XX_SYSCON_DEVCFG_TONG (1<<26) +#define EP93XX_SYSCON_DEVCFG_MONG (1<<25) +#define EP93XX_SYSCON_DEVCFG_U3EN (1<<24) +#define EP93XX_SYSCON_DEVCFG_CPENA (1<<23) +#define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22) +#define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21) +#define EP93XX_SYSCON_DEVCFG_U2EN (1<<20) +#define EP93XX_SYSCON_DEVCFG_EXVC (1<<19) +#define EP93XX_SYSCON_DEVCFG_U1EN (1<<18) +#define EP93XX_SYSCON_DEVCFG_TIN (1<<17) +#define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15) +#define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14) +#define EP93XX_SYSCON_DEVCFG_HC1IN (1<<13) +#define EP93XX_SYSCON_DEVCFG_HC1EN (1<<12) +#define EP93XX_SYSCON_DEVCFG_HONIDE (1<<11) +#define EP93XX_SYSCON_DEVCFG_GONIDE (1<<10) +#define EP93XX_SYSCON_DEVCFG_PONG (1<<9) +#define EP93XX_SYSCON_DEVCFG_EONIDE (1<<8) +#define EP93XX_SYSCON_DEVCFG_I2SONSSP (1<<7) +#define EP93XX_SYSCON_DEVCFG_I2SONAC97 (1<<6) +#define EP93XX_SYSCON_DEVCFG_RASONP3 (1<<4) +#define EP93XX_SYSCON_DEVCFG_RAS (1<<3) +#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) +#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) +#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 05f0f4f2f3ce8..fb5e59a3ea046 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -15,8 +15,24 @@ struct ep93xx_eth_data void ep93xx_map_io(void); void ep93xx_init_irq(void); void ep93xx_init_time(unsigned long); + +/* EP93xx System Controller software locked register write */ +void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg); +void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits); + +static inline void ep93xx_devcfg_set_bits(unsigned int bits) +{ + ep93xx_devcfg_set_clear(bits, 0x00); +} + +static inline void ep93xx_devcfg_clear_bits(unsigned int bits) +{ + ep93xx_devcfg_set_clear(0x00, bits); +} + void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_i2c(struct i2c_board_info *devices, int num); + void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h index ed8f35e4f068f..6d661fe9d66c0 100644 --- a/arch/arm/mach-ep93xx/include/mach/system.h +++ b/arch/arm/mach-ep93xx/include/mach/system.h @@ -11,15 +11,13 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - u32 devicecfg; - local_irq_disable(); - devicecfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(devicecfg | 0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); - __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); - __raw_writel(devicecfg & ~0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); + /* + * Set then clear the SWRST bit to initiate a software reset + */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST); + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST); while (1) ; -- GitLab From 701fac823e24676ea42451c6597f96d81d9b6aba Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Tue, 30 Jun 2009 23:06:43 +0100 Subject: [PATCH 0887/1002] [ARM] 5578/1: ep93xx: add ep93xx-keypad clock Add clkdev support for the ep93xx_keypad driver. A matrix keypad driver for the ep93xx just got merged via the input subsystem group. For this driver to work the keypad clock needs to be added to the ep93xx clkdev support. In order to accomplish this the following changes are implemented: 1) Move the EP93XX_EXT_*_RATE defines to mach/include/hardware.h. 2) Add EP93XX_KEYTCHCLK_DIV{4/16} for the keypad driver. 3) Add support for programmable clocks (set_rate() callback). 4) Add clk_keypad for the keypad driver. 5) tab indent the clk_lookup table for easier reading. 6) Add the set_rate() callback to program the keypad clock. This callback is generalized since the ADC clock (touchscreen) can use the same callback. 7) Use the ep93xx_syscon_swlocked_write() core function for updating the software locked register. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/clock.c | 101 +++++++++++++------ arch/arm/mach-ep93xx/include/mach/hardware.h | 14 +++ 2 files changed, 82 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index c7642acfd0224..207e27699410e 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -22,18 +22,6 @@ #include <mach/hardware.h> -/* - * The EP93xx has two external crystal oscillators. To generate the - * required high-frequency clocks, the processor uses two phase-locked- - * loops (PLLs) to multiply the incoming external clock signal to much - * higher frequencies that are then divided down by programmable dividers - * to produce the needed clocks. The PLLs operate independently of one - * another. - */ -#define EP93XX_EXT_CLK_RATE 14745600 -#define EP93XX_EXT_RTC_RATE 32768 - - struct clk { unsigned long rate; int users; @@ -42,11 +30,14 @@ struct clk { u32 enable_mask; unsigned long (*get_rate)(struct clk *clk); + int (*set_rate)(struct clk *clk, unsigned long rate); }; static unsigned long get_uart_rate(struct clk *clk); +static int set_keytchclk_rate(struct clk *clk, unsigned long rate); + static struct clk clk_uart1 = { .sw_locked = 1, @@ -75,6 +66,12 @@ static struct clk clk_usb_host = { .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN, }; +static struct clk clk_keypad = { + .sw_locked = 1, + .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV, + .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN, + .set_rate = set_keytchclk_rate, +}; /* DMA Clocks */ static struct clk clk_m2p0 = { @@ -130,27 +127,28 @@ static struct clk clk_m2m1 = { { .dev_id = dev, .con_id = con, .clk = ck } static struct clk_lookup clocks[] = { - INIT_CK("apb:uart1", NULL, &clk_uart1), - INIT_CK("apb:uart2", NULL, &clk_uart2), - INIT_CK("apb:uart3", NULL, &clk_uart3), - INIT_CK(NULL, "pll1", &clk_pll1), - INIT_CK(NULL, "fclk", &clk_f), - INIT_CK(NULL, "hclk", &clk_h), - INIT_CK(NULL, "pclk", &clk_p), - INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), - INIT_CK(NULL, "m2p0", &clk_m2p0), - INIT_CK(NULL, "m2p1", &clk_m2p1), - INIT_CK(NULL, "m2p2", &clk_m2p2), - INIT_CK(NULL, "m2p3", &clk_m2p3), - INIT_CK(NULL, "m2p4", &clk_m2p4), - INIT_CK(NULL, "m2p5", &clk_m2p5), - INIT_CK(NULL, "m2p6", &clk_m2p6), - INIT_CK(NULL, "m2p7", &clk_m2p7), - INIT_CK(NULL, "m2p8", &clk_m2p8), - INIT_CK(NULL, "m2p9", &clk_m2p9), - INIT_CK(NULL, "m2m0", &clk_m2m0), - INIT_CK(NULL, "m2m1", &clk_m2m1), + INIT_CK("apb:uart1", NULL, &clk_uart1), + INIT_CK("apb:uart2", NULL, &clk_uart2), + INIT_CK("apb:uart3", NULL, &clk_uart3), + INIT_CK(NULL, "pll1", &clk_pll1), + INIT_CK(NULL, "fclk", &clk_f), + INIT_CK(NULL, "hclk", &clk_h), + INIT_CK(NULL, "pclk", &clk_p), + INIT_CK(NULL, "pll2", &clk_pll2), + INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), + INIT_CK("ep93xx-keypad", NULL, &clk_keypad), + INIT_CK(NULL, "m2p0", &clk_m2p0), + INIT_CK(NULL, "m2p1", &clk_m2p1), + INIT_CK(NULL, "m2p2", &clk_m2p2), + INIT_CK(NULL, "m2p3", &clk_m2p3), + INIT_CK(NULL, "m2p4", &clk_m2p4), + INIT_CK(NULL, "m2p5", &clk_m2p5), + INIT_CK(NULL, "m2p6", &clk_m2p6), + INIT_CK(NULL, "m2p7", &clk_m2p7), + INIT_CK(NULL, "m2p8", &clk_m2p8), + INIT_CK(NULL, "m2p9", &clk_m2p9), + INIT_CK(NULL, "m2m0", &clk_m2m0), + INIT_CK(NULL, "m2m1", &clk_m2m1), }; @@ -206,6 +204,43 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); +static int set_keytchclk_rate(struct clk *clk, unsigned long rate) +{ + u32 val; + u32 div_bit; + + val = __raw_readl(clk->enable_reg); + + /* + * The Key Matrix and ADC clocks are configured using the same + * System Controller register. The clock used will be either + * 1/4 or 1/16 the external clock rate depending on the + * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV + * bit being set or cleared. + */ + div_bit = clk->enable_mask >> 15; + + if (rate == EP93XX_KEYTCHCLK_DIV4) + val |= div_bit; + else if (rate == EP93XX_KEYTCHCLK_DIV16) + val &= ~div_bit; + else + return -EINVAL; + + ep93xx_syscon_swlocked_write(val, clk->enable_reg); + clk->rate = rate; + return 0; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk->set_rate) + return clk->set_rate(clk, rate); + + return -EINVAL; +} +EXPORT_SYMBOL(clk_set_rate); + static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h index 2866297310b7c..587c07bdec5b7 100644 --- a/arch/arm/mach-ep93xx/include/mach/hardware.h +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h @@ -12,4 +12,18 @@ #include "ts72xx.h" +/* + * The EP93xx has two external crystal oscillators. To generate the + * required high-frequency clocks, the processor uses two phase-locked- + * loops (PLLs) to multiply the incoming external clock signal to much + * higher frequencies that are then divided down by programmable dividers + * to produce the needed clocks. The PLLs operate independently of one + * another. + */ +#define EP93XX_EXT_CLK_RATE 14745600 +#define EP93XX_EXT_RTC_RATE 32768 + +#define EP93XX_KEYTCHCLK_DIV4 (EP93XX_EXT_CLK_RATE / 4) +#define EP93XX_KEYTCHCLK_DIV16 (EP93XX_EXT_CLK_RATE / 16) + #endif -- GitLab From 583ddafe1787528d08b0026bb3273490a499b730 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Mon, 6 Jul 2009 17:39:50 +0100 Subject: [PATCH 0888/1002] [ARM] 5592/1: ep93xx: cleanup platform header includes arch/arm/mach-ep93xx/include/mach/hardware.h 1. Properly name the include files so that they are loaded from the <mach/*> directory and not the local directory. 2. Remove including the ts72xx.h header. This header is not generic to the ep93xx platform. It should only be included by the ts72xx specific files that require it. The only two users in the tree are arch/arm/mach-ep93xx/ts72xx.c and drivers/mtd/nand/ts7250.c. arch/arm/mach-ep93xx/include/mach/ts72xx.h 1. <linux/io.h> should already be included by any user of this header. Doing the include here hides it from being needed by the calling source file. arch/arm/mach-ep93xx/core.c 1. Remove unnecessary headers. They were probably included originally due to cut-and-paste from other files. 2. <linux/io.h> should be included not <mach/gpio.h> arch/arm/mach-ep93xx/adsphere.c arch/arm/mach-ep93xx/edb93xx.c arch/arm/mach-ep93xx/gesbc9312.c arch/arm/mach-ep93xx/micro9.c arch/arm/mach-ep93xx/ts72xx.c 1. Remove unnecessary headers. arch/arm/mach-ep93xx/ts72xx.c 1. Remove unnecessary headers. 2. Add platform specific header <mach/ts72xx.h>. drivers/mtd/nand/ts7250.c 1. <linux/io.h> should be included not <asm/io.h>. 2. Add platform specific header <mach/ts72xx.h>. Cc: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/adssphere.c | 11 ++++------ arch/arm/mach-ep93xx/core.c | 23 +++----------------- arch/arm/mach-ep93xx/edb93xx.c | 10 ++++----- arch/arm/mach-ep93xx/gesbc9312.c | 11 ++++------ arch/arm/mach-ep93xx/include/mach/hardware.h | 7 ++---- arch/arm/mach-ep93xx/include/mach/ts72xx.h | 1 - arch/arm/mach-ep93xx/micro9.c | 11 +++------- arch/arm/mach-ep93xx/ts72xx.c | 15 ++++++------- drivers/mtd/nand/ts7250.c | 5 ++++- 9 files changed, 31 insertions(+), 63 deletions(-) diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index 3fbd9b0fbe24e..caf6d5154aecd 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -12,18 +12,15 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/mtd/physmap.h> #include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/i2c.h> +#include <linux/mtd/physmap.h> + #include <mach/hardware.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> + static struct physmap_flash_data adssphere_flash_data = { .width = 4, }; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 9399d3af9906e..ce10f5b5dfbb9 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -16,40 +16,23 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/sched.h> +#include <linux/platform_device.h> #include <linux/interrupt.h> -#include <linux/serial.h> -#include <linux/tty.h> -#include <linux/bitops.h> -#include <linux/serial_8250.h> -#include <linux/serial_core.h> -#include <linux/device.h> -#include <linux/mm.h> #include <linux/dma-mapping.h> -#include <linux/time.h> #include <linux/timex.h> -#include <linux/delay.h> +#include <linux/io.h> +#include <linux/gpio.h> #include <linux/termios.h> #include <linux/amba/bus.h> #include <linux/amba/serial.h> -#include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c-gpio.h> -#include <asm/types.h> -#include <asm/setup.h> -#include <asm/memory.h> #include <mach/hardware.h> -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/tlbflush.h> -#include <asm/pgtable.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/mach/irq.h> -#include <mach/gpio.h> #include <asm/hardware/vic.h> diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index e9e45b92457e6..73145ae5d3fa3 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -26,18 +26,16 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/mtd/physmap.h> #include <linux/platform_device.h> -#include <linux/io.h> #include <linux/i2c.h> +#include <linux/mtd/physmap.h> + #include <mach/hardware.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> + static struct physmap_flash_data edb93xx_flash_data; static struct resource edb93xx_flash_resource = { diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index 3bad500b71b69..3da7ca816d195 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -12,18 +12,15 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/mtd/physmap.h> #include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/i2c.h> +#include <linux/mtd/physmap.h> + #include <mach/hardware.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> + static struct physmap_flash_data gesbc9312_flash_data = { .width = 4, }; diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h index 587c07bdec5b7..349fa7cb72d56 100644 --- a/arch/arm/mach-ep93xx/include/mach/hardware.h +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h @@ -4,14 +4,11 @@ #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H -#include "ep93xx-regs.h" +#include <mach/ep93xx-regs.h> +#include <mach/platform.h> #define pcibios_assign_all_busses() 0 -#include "platform.h" - -#include "ts72xx.h" - /* * The EP93xx has two external crystal oscillators. To generate the * required high-frequency clocks, the processor uses two phase-locked- diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h index 34ddec081c40d..2737666e800e9 100644 --- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h +++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h @@ -70,7 +70,6 @@ #ifndef __ASSEMBLY__ -#include <linux/io.h> static inline int board_is_ts7200(void) { diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index 15d6815d78c41..0a313e82fb744 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -9,21 +9,16 @@ * published by the Free Software Foundation. */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> #include <linux/kernel.h> -#include <linux/mm.h> +#include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/io.h> -#include <linux/i2c.h> #include <linux/mtd/physmap.h> #include <mach/hardware.h> -#include <asm/mach/arch.h> #include <asm/mach-types.h> +#include <asm/mach/arch.h> + static struct ep93xx_eth_data micro9_eth_data = { .phy_id = 0x1f, diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 7ee024d348298..5255dddd3067a 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -12,19 +12,18 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/mtd/physmap.h> #include <linux/platform_device.h> -#include <linux/m48t86.h> #include <linux/io.h> -#include <linux/i2c.h> +#include <linux/m48t86.h> +#include <linux/mtd/physmap.h> + #include <mach/hardware.h> +#include <mach/ts72xx.h> + #include <asm/mach-types.h> -#include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/mach/arch.h> + static struct map_desc ts72xx_io_desc[] __initdata = { { diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c index 2c410a011317a..0f5562aeedc1c 100644 --- a/drivers/mtd/nand/ts7250.c +++ b/drivers/mtd/nand/ts7250.c @@ -24,8 +24,11 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> -#include <asm/io.h> +#include <linux/io.h> + #include <mach/hardware.h> +#include <mach/ts72xx.h> + #include <asm/sizes.h> #include <asm/mach-types.h> -- GitLab From c3e3baddbc0b6636b01cb2aa3e44505ad61be17b Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Mon, 6 Jul 2009 17:40:53 +0100 Subject: [PATCH 0889/1002] [ARM] 5593/1: ep93xx: clock.c __iomem pointer To ensure typesafe io, the enable_reg variable should be a void __iomem pointer not u32. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 207e27699410e..b6b53447b1b47 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -26,7 +26,7 @@ struct clk { unsigned long rate; int users; int sw_locked; - u32 enable_reg; + void __iomem *enable_reg; u32 enable_mask; unsigned long (*get_rate)(struct clk *clk); -- GitLab From 19c0a7286f3f0093bbbbcdce0af4c3205421b608 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Sat, 4 Jul 2009 12:26:33 +0100 Subject: [PATCH 0890/1002] [ARM] 5591/1: Add group irq enable/disable for w90p910 platform. Add group irq enable/disable for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/irq.c | 154 ++++++++++++++++++++++++++++++++++-- 1 file changed, 146 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-w90x900/irq.c b/arch/arm/mach-w90x900/irq.c index 0b4fc194729c7..a296c9b81d244 100644 --- a/arch/arm/mach-w90x900/irq.c +++ b/arch/arm/mach-w90x900/irq.c @@ -10,8 +10,7 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation;version 2 of the License. * */ @@ -29,9 +28,114 @@ #include <mach/hardware.h> #include <mach/regs-irq.h> +struct group_irq { + unsigned long gpen; + unsigned int enabled; + void (*enable)(struct group_irq *, int enable); +}; + +static DEFINE_SPINLOCK(groupirq_lock); + +#define DEFINE_GROUP(_name, _ctrlbit, _num) \ +struct group_irq group_##_name = { \ + .enable = w90x900_group_enable, \ + .gpen = ((2 ^ _num) - 1) << _ctrlbit, \ + } + +static void w90x900_group_enable(struct group_irq *gpirq, int enable); + +static DEFINE_GROUP(nirq0, 0, 4); +static DEFINE_GROUP(nirq1, 4, 4); +static DEFINE_GROUP(usbh, 8, 2); +static DEFINE_GROUP(ottimer, 16, 3); +static DEFINE_GROUP(gdma, 20, 2); +static DEFINE_GROUP(sc, 24, 2); +static DEFINE_GROUP(i2c, 26, 2); +static DEFINE_GROUP(ps2, 28, 2); + +static int group_irq_enable(struct group_irq *group_irq) +{ + unsigned long flags; + + spin_lock_irqsave(&groupirq_lock, flags); + if (group_irq->enabled++ == 0) + (group_irq->enable)(group_irq, 1); + spin_unlock_irqrestore(&groupirq_lock, flags); + + return 0; +} + +static void group_irq_disable(struct group_irq *group_irq) +{ + unsigned long flags; + + WARN_ON(group_irq->enabled == 0); + + spin_lock_irqsave(&groupirq_lock, flags); + if (--group_irq->enabled == 0) + (group_irq->enable)(group_irq, 0); + spin_unlock_irqrestore(&groupirq_lock, flags); +} + +static void w90x900_group_enable(struct group_irq *gpirq, int enable) +{ + unsigned int groupen = gpirq->gpen; + unsigned long regval; + + regval = __raw_readl(REG_AIC_GEN); + + if (enable) + regval |= groupen; + else + regval &= ~groupen; + + __raw_writel(regval, REG_AIC_GEN); +} + static void w90x900_irq_mask(unsigned int irq) { + struct group_irq *group_irq; + + group_irq = NULL; + __raw_writel(1 << irq, REG_AIC_MDCR); + + switch (irq) { + case IRQ_GROUP0: + group_irq = &group_nirq0; + break; + + case IRQ_GROUP1: + group_irq = &group_nirq1; + break; + + case IRQ_USBH: + group_irq = &group_usbh; + break; + + case IRQ_T_INT_GROUP: + group_irq = &group_ottimer; + break; + + case IRQ_GDMAGROUP: + group_irq = &group_gdma; + break; + + case IRQ_SCGROUP: + group_irq = &group_sc; + break; + + case IRQ_I2CGROUP: + group_irq = &group_i2c; + break; + + case IRQ_P2SGROUP: + group_irq = &group_ps2; + break; + } + + if (group_irq) + group_irq_disable(group_irq); } /* @@ -46,14 +150,48 @@ static void w90x900_irq_ack(unsigned int irq) static void w90x900_irq_unmask(unsigned int irq) { - unsigned long mask; + struct group_irq *group_irq; + + group_irq = NULL; - if (irq == IRQ_T_INT_GROUP) { - mask = __raw_readl(REG_AIC_GEN); - __raw_writel(TIME_GROUP_IRQ | mask, REG_AIC_GEN); - __raw_writel(1 << IRQ_T_INT_GROUP, REG_AIC_MECR); - } __raw_writel(1 << irq, REG_AIC_MECR); + + switch (irq) { + case IRQ_GROUP0: + group_irq = &group_nirq0; + break; + + case IRQ_GROUP1: + group_irq = &group_nirq1; + break; + + case IRQ_USBH: + group_irq = &group_usbh; + break; + + case IRQ_T_INT_GROUP: + group_irq = &group_ottimer; + break; + + case IRQ_GDMAGROUP: + group_irq = &group_gdma; + break; + + case IRQ_SCGROUP: + group_irq = &group_sc; + break; + + case IRQ_I2CGROUP: + group_irq = &group_i2c; + break; + + case IRQ_P2SGROUP: + group_irq = &group_ps2; + break; + } + + if (group_irq) + group_irq_enable(group_irq); } static struct irq_chip w90x900_irq_chip = { -- GitLab From d7dbf6ea40a2859adaca2dfdbbea83f3d6c73c2f Mon Sep 17 00:00:00 2001 From: Mark Brown <broonie@sirena.org.uk> Date: Wed, 8 Jul 2009 21:12:20 +0100 Subject: [PATCH 0891/1002] [ARM] 5596/1: at91sam9g20-ek: Register WM8731 in board file The WM8731 driver has been updated to allow registration via normal device model methods rather than from within the ASoC driver probe so update the AT91SAM9G20-EK to make use of this. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-sam9g20ek.c | 1 + sound/soc/atmel/sam9g20_wm8731.c | 36 ---------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index cc270beadd5d6..4c2598700882d 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -221,6 +221,7 @@ static struct gpio_led ek_leds[] = { static struct i2c_board_info __initdata ek_i2c_devices[] = { { I2C_BOARD_INFO("24c512", 0x50), + I2C_BOARD_INFO("wm8731", 0x1b), }, }; diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 173a239a541c3..bb0db55e0e98f 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -281,38 +281,6 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { .set_bias_level = at91sam9g20ek_set_bias_level, }; -/* - * FIXME: This is a temporary bodge to avoid cross-tree merge issues. - * New drivers should register the wm8731 I2C device in the machine - * setup code (under arch/arm for ARM systems). - */ -static int wm8731_i2c_register(void) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = 0x1b; - strlcpy(info.type, "wm8731", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(0); - if (!adapter) { - printk(KERN_ERR "can't get i2c adapter 0\n"); - return -ENODEV; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - printk(KERN_ERR "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - return -ENODEV; - } - - return 0; -} - static struct snd_soc_device at91sam9g20ek_snd_devdata = { .card = &snd_soc_at91sam9g20ek, .codec_dev = &soc_codec_dev_wm8731, @@ -367,10 +335,6 @@ static int __init at91sam9g20ek_init(void) } ssc_p->ssc = ssc; - ret = wm8731_i2c_register(); - if (ret != 0) - goto err_ssc; - at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); if (!at91sam9g20ek_snd_device) { printk(KERN_ERR "ASoC: Platform device allocation failed\n"); -- GitLab From 005b10769c05fb16db70f7689ffb5ba17e3fc324 Mon Sep 17 00:00:00 2001 From: David Heidelberger <d.okias@gmail.com> Date: Thu, 9 Jul 2009 18:45:46 +0200 Subject: [PATCH 0892/1002] ALSA: hda - targa and targa-2ch fix Simplify ALC882_TARGA and return gpio3 to ALC883_TARGA_DIG and ALC883_TARGA_2ch_DIG, which I accidentally removed in commit id 64a8be74357477558183b43156c5536b642de134 Signed-off-by: David Heidelberger <d.okias@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> --- sound/pci/hda/patch_realtek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c6c3d4a4d6486..bbb9b42e2604c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6919,9 +6919,6 @@ static struct hda_verb alc882_targa_verbs[] = { {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, { } /* end */ }; @@ -7241,7 +7238,8 @@ static struct alc_config_preset alc882_presets[] = { }, [ALC882_TARGA] = { .mixers = { alc882_targa_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_targa_verbs}, + .init_verbs = { alc882_init_verbs, alc880_gpio3_init_verbs, + alc882_targa_verbs}, .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, .dig_out_nid = ALC882_DIGOUT_NID, @@ -9238,7 +9236,8 @@ static struct alc_config_preset alc883_presets[] = { }, [ALC883_TARGA_DIG] = { .mixers = { alc883_targa_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs, alc883_targa_verbs}, + .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs, + alc883_targa_verbs}, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .dac_nids = alc883_dac_nids, .dig_out_nid = ALC883_DIGOUT_NID, @@ -9251,7 +9250,8 @@ static struct alc_config_preset alc883_presets[] = { }, [ALC883_TARGA_2ch_DIG] = { .mixers = { alc883_targa_2ch_mixer}, - .init_verbs = { alc883_init_verbs, alc883_targa_verbs}, + .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs, + alc883_targa_verbs}, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, -- GitLab From b86a6c6c7b0bfc26b3e8d4f48e16ee0b13716385 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 28 Jun 2009 09:26:57 -0700 Subject: [PATCH 0893/1002] [WATCHDOG] drivers/watchdog/bcm47xx_wdt.c: Remove unnecessary semicolons Signed-off-by: Joe Perches <joe@perches.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> --- drivers/watchdog/bcm47xx_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c index 5c7011cda6a6a..751c003864ad6 100644 --- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -161,7 +161,7 @@ static long bcm47xx_wdt_ioctl(struct file *file, { void __user *argp = (void __user *)arg; int __user *p = argp; - int new_value, retval = -EINVAL;; + int new_value, retval = -EINVAL; switch (cmd) { case WDIOC_GETSUPPORT: -- GitLab From db5d2d8a5dfe0ae3e83ac618fd953ecc621adcdf Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jirislaby@gmail.com> Date: Mon, 29 Jun 2009 18:00:39 +0200 Subject: [PATCH 0894/1002] [WATCHDOG] w83697ug, fix lock imbalance Don't forget to unlock io_lock when w83697ug_select_wd_register fails in wdt_ctrl. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> --- drivers/watchdog/w83697ug_wdt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index 883b5f79673a6..a6c12dec91a14 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -149,8 +149,10 @@ static void wdt_ctrl(int timeout) { spin_lock(&io_lock); - if (w83697ug_select_wd_register() < 0) + if (w83697ug_select_wd_register() < 0) { + spin_unlock(&io_lock); return; + } outb_p(0xF4, WDT_EFER); /* Select CRF4 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ -- GitLab From a6f052e39c3832b5842c4f44d9b3a4295dacfc4a Mon Sep 17 00:00:00 2001 From: Raphael Assenat <raph@8d.com> Date: Mon, 29 Jun 2009 13:56:52 -0400 Subject: [PATCH 0895/1002] [WATCHDOG] SA1100 watchdog maximum timeout This patch replaces the hardcoded 255 seconds limit for a real limit based on oscr_freq. Also, the 'firmware_version' field is changed to '1' to allow the user space application to easily detect that this driver supports a higher maximum timeout. Signed-off-by: Raphael Assenat <raph@8D.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> --- drivers/watchdog/sa1100_wdt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index ee1caae4d33b0..016245419fadb 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -38,7 +38,7 @@ static unsigned long oscr_freq; static unsigned long sa1100wdt_users; -static int pre_margin; +static unsigned int pre_margin; static int boot_status; /* @@ -84,6 +84,7 @@ static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "SA1100/PXA255 Watchdog", + .firmware_version = 1, }; static long sa1100dog_ioctl(struct file *file, unsigned int cmd, @@ -118,7 +119,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (time <= 0 || time > 255) { + if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) { ret = -EINVAL; break; } -- GitLab From cf1eaab2525e8ae1d53eaf923981c96cb31e57c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Slobodan=20Tomi=C4=87?= <stomic@gmail.com> Date: Sun, 28 Jun 2009 21:20:36 +0200 Subject: [PATCH 0896/1002] [WATCHDOG] w83627hf_wdt.c: add support for the W83627EHF support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the W83627EHF/EF and W83627EHG/EG chipsets. Signed-off-by: Slobodan Tomić <stomic@gmail.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> --- drivers/watchdog/w83627hf_wdt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 916890abffdd3..f201accc4e3d9 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -89,6 +89,11 @@ static void w83627hf_select_wd_register(void) c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ outb_p(0x2b, WDT_EFER); outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ + } else if (c == 0x88) { /* W83627EHF */ + outb_p(0x2d, WDT_EFER); /* select GPIO5 */ + c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ + outb_p(0x2d, WDT_EFER); + outb_p(c, WDT_EFDR); /* set GPIO5 to WDT0 */ } outb_p(0x07, WDT_EFER); /* point to logical device number reg */ -- GitLab From 13892cf95d2edf0d3c4285cc2d0113efa73be723 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Thu, 9 Jul 2009 20:56:14 +0100 Subject: [PATCH 0897/1002] [ARM] Update mach-types Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/tools/mach-types | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 33026eff2aa47..30af432946935 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sat Jun 20 22:28:39 2009 +# Last update: Thu Jul 9 20:56:13 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1769,7 +1769,7 @@ mx31cicada MACH_MX31CICADA MX31CICADA 1777 mi424wr MACH_MI424WR MI424WR 1778 axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779 at572d940deb MACH_AT572D940DEB AT572D940DEB 1780 -davinci_da8xx_evm MACH_DAVINCI_DA8XX_EVM DAVINCI_DA8XX_EVM 1781 +davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781 ep9302 MACH_EP9302 EP9302 1782 at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783 cybook3 MACH_CYBOOK3 CYBOOK3 1784 @@ -2280,3 +2280,36 @@ htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292 htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293 matrix504 MACH_MATRIX504 MATRIX504 2294 mrfsa MACH_MRFSA MRFSA 2295 +sc_p270 MACH_SC_P270 SC_P270 2296 +atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297 +pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298 +dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299 +leonardo MACH_LEONARDO LEONARDO 2300 +zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301 +dp6xx MACH_DP6XX DP6XX 2302 +bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303 +mahimahi MACH_MAHIMAHI MAHIMAHI 2304 +clickc MACH_CLICKC CLICKC 2305 +zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306 +tazcard MACH_TAZCARD TAZCARD 2307 +tazdev MACH_TAZDEV TAZDEV 2308 +annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309 +annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310 +cerebric MACH_CEREBRIC CEREBRIC 2311 +orca MACH_ORCA ORCA 2312 +pc9260 MACH_PC9260 PC9260 2313 +ems285a MACH_EMS285A EMS285A 2314 +gec2410 MACH_GEC2410 GEC2410 2315 +gec2440 MACH_GEC2440 GEC2440 2316 +mw903 MACH_ARCH_MW903 ARCH_MW903 2317 +mw2440 MACH_MW2440 MW2440 2318 +ecac2378 MACH_ECAC2378 ECAC2378 2319 +tazkiosk MACH_TAZKIOSK TAZKIOSK 2320 +whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321 +sbox9263 MACH_SBOX9263 SBOX9263 2322 +oreo MACH_OREO OREO 2323 +smdk6442 MACH_SMDK6442 SMDK6442 2324 +openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 +incredible MACH_INCREDIBLE INCREDIBLE 2326 +incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 +heroct MACH_HEROCT HEROCT 2328 -- GitLab From c4c1bff64dfff4e6dd0936a0340f56b9284512c8 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 20:02:48 -0400 Subject: [PATCH 0898/1002] cifs: add pid of initiating process to spnego upcall info cifs: add pid of initiating process to spnego upcall info This will allow the upcall to poke in /proc/<pid>/environ and get the value of the $KRB5CCNAME env var for the process. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifs_spnego.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 4a4581cb2b5e3..051caecf7d677 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -86,6 +86,9 @@ struct key_type cifs_spnego_key_type = { /* strlen of ";user=" */ #define USER_KEY_LEN 6 +/* strlen of ";pid=0x" */ +#define PID_KEY_LEN 7 + /* get a key struct with a SPNEGO security blob, suitable for session setup */ struct key * cifs_get_spnego_key(struct cifsSesInfo *sesInfo) @@ -103,7 +106,8 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) IP_KEY_LEN + INET6_ADDRSTRLEN + MAX_MECH_STR_LEN + UID_KEY_LEN + (sizeof(uid_t) * 2) + - USER_KEY_LEN + strlen(sesInfo->userName) + 1; + USER_KEY_LEN + strlen(sesInfo->userName) + + PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; spnego_key = ERR_PTR(-ENOMEM); description = kzalloc(desc_len, GFP_KERNEL); @@ -141,6 +145,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); sprintf(dp, ";user=%s", sesInfo->userName); + dp = description + strlen(description); + sprintf(dp, ";pid=0x%x", current->pid); + cFYI(1, ("key description = %s", description)); spnego_key = request_key(&cifs_spnego_key_type, description, ""); -- GitLab From 01ea95e3b6b16573a491ef98ad63f7a1bdcb504f Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 20:02:49 -0400 Subject: [PATCH 0899/1002] cifs: rename CIFSSMBUnixSetInfo to CIFSSMBUnixSetPathInfo cifs: rename CIFSSMBUnixSetInfo to CIFSSMBUnixSetPathInfo ...in preparation of adding a SET_FILE_INFO variant. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsproto.h | 2 +- fs/cifs/cifssmb.c | 6 +++--- fs/cifs/dir.c | 15 ++++++++------- fs/cifs/file.c | 6 +++--- fs/cifs/inode.c | 16 ++++++++-------- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b2bd83fd2aa48..d95fd427de573 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -220,7 +220,7 @@ struct cifs_unix_set_info_args { dev_t device; }; -extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, +extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, char *fileName, const struct cifs_unix_set_info_args *args, const struct nls_table *nls_codepage, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61007c6274975..1cd01ba036563 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5075,9 +5075,9 @@ CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, #endif /* temporarily unneeded SetAttr legacy function */ int -CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, - const struct cifs_unix_set_info_args *args, - const struct nls_table *nls_codepage, int remap) +CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, + const struct cifs_unix_set_info_args *args, + const struct nls_table *nls_codepage, int remap) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index ff55fc6932cb8..4326ffd90fa91 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -425,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { /* BB implement mode setting via Windows security descriptors e.g. */ @@ -515,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, - &args, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path, diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 97ce4bf89d152..c34b7f8a217b3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -448,9 +448,9 @@ int cifs_open(struct inode *inode, struct file *file) .mtime = NO_CHANGE_64, .device = 0, }; - CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b22379610d719..ad19007ea05ff 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1241,10 +1241,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) args.uid = NO_CHANGE_64; args.gid = NO_CHANGE_64; } - CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && (mode & S_IWUGO) == 0) { @@ -1876,10 +1876,10 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) args->ctime = NO_CHANGE_64; args->device = 0; - rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) rc = inode_setattr(inode, attrs); -- GitLab From 654cf14ac0a71c56c1f0032140c3403382ca076b Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 20:02:49 -0400 Subject: [PATCH 0900/1002] cifs: make a separate function for filling out FILE_UNIX_BASIC_INFO cifs: make a separate function for filling out FILE_UNIX_BASIC_INFO The SET_FILE_INFO variant will need to do the same thing here. Break this code out into a separate function that both variants can call. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifssmb.c | 74 +++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1cd01ba036563..1f3c8a463fcd0 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5074,6 +5074,47 @@ CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, } #endif /* temporarily unneeded SetAttr legacy function */ +static void +cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, + const struct cifs_unix_set_info_args *args) +{ + u64 mode = args->mode; + + /* + * Samba server ignores set of file size to zero due to bugs in some + * older clients, but we should be precise - we use SetFileSize to + * set file size and do not want to truncate file size to zero + * accidently as happened on one Samba server beta by putting + * zero instead of -1 here + */ + data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); + data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); + data_offset->LastStatusChange = cpu_to_le64(args->ctime); + data_offset->LastAccessTime = cpu_to_le64(args->atime); + data_offset->LastModificationTime = cpu_to_le64(args->mtime); + data_offset->Uid = cpu_to_le64(args->uid); + data_offset->Gid = cpu_to_le64(args->gid); + /* better to leave device as zero when it is */ + data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); + data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); + data_offset->Permissions = cpu_to_le64(mode); + + if (S_ISREG(mode)) + data_offset->Type = cpu_to_le32(UNIX_FILE); + else if (S_ISDIR(mode)) + data_offset->Type = cpu_to_le32(UNIX_DIR); + else if (S_ISLNK(mode)) + data_offset->Type = cpu_to_le32(UNIX_SYMLINK); + else if (S_ISCHR(mode)) + data_offset->Type = cpu_to_le32(UNIX_CHARDEV); + else if (S_ISBLK(mode)) + data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); + else if (S_ISFIFO(mode)) + data_offset->Type = cpu_to_le32(UNIX_FIFO); + else if (S_ISSOCK(mode)) + data_offset->Type = cpu_to_le32(UNIX_SOCKET); +} + int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, const struct cifs_unix_set_info_args *args, @@ -5086,7 +5127,6 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, int bytes_returned = 0; FILE_UNIX_BASIC_INFO *data_offset; __u16 params, param_offset, offset, count, byte_count; - __u64 mode = args->mode; cFYI(1, ("In SetUID/GID/Mode")); setPermsRetry: @@ -5137,38 +5177,8 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; - /* Samba server ignores set of file size to zero due to bugs in some - older clients, but we should be precise - we use SetFileSize to - set file size and do not want to truncate file size to zero - accidently as happened on one Samba server beta by putting - zero instead of -1 here */ - data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); - data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); - data_offset->LastStatusChange = cpu_to_le64(args->ctime); - data_offset->LastAccessTime = cpu_to_le64(args->atime); - data_offset->LastModificationTime = cpu_to_le64(args->mtime); - data_offset->Uid = cpu_to_le64(args->uid); - data_offset->Gid = cpu_to_le64(args->gid); - /* better to leave device as zero when it is */ - data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); - data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); - data_offset->Permissions = cpu_to_le64(mode); - - if (S_ISREG(mode)) - data_offset->Type = cpu_to_le32(UNIX_FILE); - else if (S_ISDIR(mode)) - data_offset->Type = cpu_to_le32(UNIX_DIR); - else if (S_ISLNK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SYMLINK); - else if (S_ISCHR(mode)) - data_offset->Type = cpu_to_le32(UNIX_CHARDEV); - else if (S_ISBLK(mode)) - data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); - else if (S_ISFIFO(mode)) - data_offset->Type = cpu_to_le32(UNIX_FIFO); - else if (S_ISSOCK(mode)) - data_offset->Type = cpu_to_le32(UNIX_SOCKET); + cifs_fill_unix_set_info(data_offset, args); pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, -- GitLab From 3bbeeb3c93a961bd01b969dd4395ecac0c09db8d Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 20:02:50 -0400 Subject: [PATCH 0901/1002] cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls When there's an open filehandle, SET_FILE_INFO is apparently preferred over SET_PATH_INFO. Add a new variant that sets a FILE_UNIX_INFO_BASIC infolevel via SET_FILE_INFO and switch cifs_setattr_unix to use the new call when there's an open filehandle available. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsproto.h | 4 +++ fs/cifs/cifssmb.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/inode.c | 11 +++++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d95fd427de573..37c11c08c5294 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -220,6 +220,10 @@ struct cifs_unix_set_info_args { dev_t device; }; +extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, + const struct cifs_unix_set_info_args *args, + u16 fid, u32 pid_of_opener); + extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, char *fileName, const struct cifs_unix_set_info_args *args, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1f3c8a463fcd0..922f5fe2084c9 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5115,6 +5115,69 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, data_offset->Type = cpu_to_le32(UNIX_SOCKET); } +int +CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, + const struct cifs_unix_set_info_args *args, + u16 fid, u32 pid_of_opener) +{ + struct smb_com_transaction2_sfi_req *pSMB = NULL; + FILE_UNIX_BASIC_INFO *data_offset; + int rc = 0; + u16 params, param_offset, offset, byte_count, count; + + cFYI(1, ("Set Unix Info (via SetFileInfo)")); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + + if (rc) + return rc; + + pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); + + params = 6; + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; + offset = param_offset + params; + + data_offset = (FILE_UNIX_BASIC_INFO *) + ((char *)(&pSMB->hdr.Protocol) + offset); + count = sizeof(FILE_UNIX_BASIC_INFO); + + pSMB->MaxParameterCount = cpu_to_le16(2); + /* BB find max SMB PDU from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); + byte_count = 3 /* pad */ + params + count; + pSMB->DataCount = cpu_to_le16(count); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->Fid = fid; + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + cifs_fill_unix_set_info(data_offset, args); + + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); + if (rc) + cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ + + return rc; +} + int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, const struct cifs_unix_set_info_args *args, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ad19007ea05ff..55b616bb381ef 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1790,6 +1790,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsTconInfo *pTcon = cifs_sb->tcon; struct cifs_unix_set_info_args *args = NULL; + struct cifsFileInfo *open_file; cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", direntry->d_name.name, attrs->ia_valid)); @@ -1876,10 +1877,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) args->ctime = NO_CHANGE_64; args->device = 0; - rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, + open_file = find_writable_file(cifsInode); + if (open_file) { + u16 nfid = open_file->netfid; + u32 npid = open_file->pid; + rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); + atomic_dec(&open_file->wrtPending); + } else { + rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + } if (!rc) rc = inode_setattr(inode, attrs); -- GitLab From b77863bfa153e886f9f8faf1a791ba57a36efed0 Mon Sep 17 00:00:00 2001 From: Steve French <sfrench@us.ibm.com> Date: Thu, 9 Jul 2009 22:51:38 +0000 Subject: [PATCH 0902/1002] [CIFS] update cifs version number Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/CHANGES | 6 +++++- fs/cifs/cifsfs.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3a9b7a58a51d0..92888aa907492 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -5,7 +5,11 @@ client generated ones by default (mount option "serverino" turned on by default if server supports it). Add forceuid and forcegid mount options (so that when negotiating unix extensions specifying which uid mounted does not immediately force the server's reported -uids to be overridden). Add support for scope moutn parm. +uids to be overridden). Add support for scope mount parm. Improve +hard link detection to use same inode for both. Do not set +read-only dos attribute on directories (for chmod) since Windows +explorer special cases this attribute bit for directories for +a different purpose. Version 1.58 ------------ diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 586df24c9abb6..6c170948300d9 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -113,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.59" +#define CIFS_VERSION "1.60" #endif /* _CIFSFS_H */ -- GitLab From e99da35f060f9a3407f7def474a1df31f3b8643a Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Fri, 26 Jun 2009 09:46:18 +0800 Subject: [PATCH 0903/1002] drm/i915: Check the LID device to decide whether the LVDS should be initialized On some boxes the mobile chipset is used and there is no LVDS device. In such case we had better not initialize the LVDS output device so that one pipe can be used for other output device. For example: E-TOP. But unfortunately the LVDS device is still initialized on the boxes based on mobile chipset in KMS mode. It brings that this pipe occupied by LVDS can't be used for other output device. After checking the acpidump we find that there is no LID device on such boxes. In such case we can use the LID device to decide whether the LVDS device should be initialized. If there is no LID device, we can think that there is no LVDS device. It is unnecessary to initialize the LVDS output device. If there exists the LID device, it will continue the current flowchart. Maybe on some boxes there is no LVDS device but the LID device is found. In such case it should be added to the quirk list. http://bugs.freedesktop.org/show_bug.cgi?id=21496 http://bugs.freedesktop.org/show_bug.cgi?id=21856 http://bugs.freedesktop.org/show_bug.cgi?id=21127 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> [anholt: squashed in style fixups] Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_lvds.c | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f65044b1647b2..9ab38efffecfe 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -36,6 +36,7 @@ #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" +#include <linux/acpi.h> #define I915_LVDS "i915_lvds" @@ -788,6 +789,65 @@ static const struct dmi_system_id intel_no_lvds[] = { { } /* terminating entry */ }; +#ifdef CONFIG_ACPI +/* + * check_lid_device -- check whether @handle is an ACPI LID device. + * @handle: ACPI device handle + * @level : depth in the ACPI namespace tree + * @context: the number of LID device when we find the device + * @rv: a return value to fill if desired (Not use) + */ +static acpi_status +check_lid_device(acpi_handle handle, u32 level, void *context, + void **return_value) +{ + struct acpi_device *acpi_dev; + int *lid_present = context; + + acpi_dev = NULL; + /* Get the acpi device for device handle */ + if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { + /* If there is no ACPI device for handle, return */ + return AE_OK; + } + + if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) + *lid_present = 1; + + return AE_OK; +} + +/** + * check whether there exists the ACPI LID device by enumerating the ACPI + * device tree. + */ +static int intel_lid_present(void) +{ + int lid_present = 0; + + if (acpi_disabled) { + /* If ACPI is disabled, there is no ACPI device tree to + * check, so assume the LID device would have been present. + */ + return 1; + } + + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + check_lid_device, &lid_present, NULL); + + return lid_present; +} +#else +static int intel_lid_present(void) +{ + /* In the absence of ACPI built in, assume that the LID device would + * have been present. + */ + return 1; +} +#endif + /** * intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -811,6 +871,16 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; + /* Assume that any device without an ACPI LID device also doesn't + * have an integrated LVDS. We would be better off parsing the BIOS + * to get a reliable indicator, but that code isn't written yet. + * + * In the case of all-in-one desktops using LVDS that we've seen, + * they're using SDVO LVDS. + */ + if (!intel_lid_present()) + return; + if (IS_IGDNG(dev)) { if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) return; -- GitLab From 0b8f18e358384a52c1ed7fa7129c08e7eaf86bb6 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 01:46:37 -0400 Subject: [PATCH 0904/1002] cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget Rather than allocating an inode and filling it out, have cifs_get_inode_info fill out a cifs_fattr and call cifs_iget. This means a pretty hefty reorganization of cifs_get_inode_info. For the readdir codepath, add a couple of new functions for filling out cifs_fattr's from different FindFile response infolevels. Finally, remove cifs_new_inode since there are no more callers. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsacl.c | 26 +-- fs/cifs/cifsglob.h | 2 + fs/cifs/cifsproto.h | 6 +- fs/cifs/inode.c | 397 +++++++++++++++++--------------------------- fs/cifs/readdir.c | 350 +++++++++----------------------------- 5 files changed, 252 insertions(+), 529 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1403b5d86a739..6941c22398a6a 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, - struct inode *inode) + struct cifs_fattr *fattr) { int i; int num_aces = 0; @@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, if (!pdacl) { /* no DACL in the security descriptor, set all the permissions for user/group/other */ - inode->i_mode |= S_IRWXUGO; + fattr->cf_mode |= S_IRWXUGO; return; } @@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, /* reset rwx permissions for user/group/other. Also, if num_aces is 0 i.e. DACL has no ACEs, user/group/other have no permissions */ - inode->i_mode &= ~(S_IRWXUGO); + fattr->cf_mode &= ~(S_IRWXUGO); acl_base = (char *)pdacl; acl_size = sizeof(struct cifs_acl); @@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, if (compare_sids(&(ppace[i]->sid), pownersid)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &user_mask); if (compare_sids(&(ppace[i]->sid), pgrpsid)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &group_mask); if (compare_sids(&(ppace[i]->sid), &sid_everyone)) access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, - &(inode->i_mode), + &fattr->cf_mode, &other_mask); /* memcpy((void *)(&(cifscred->aces[i])), @@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) /* Convert CIFS ACL to POSIX form */ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, - struct inode *inode) + struct cifs_fattr *fattr) { int rc; struct cifs_sid *owner_sid_ptr, *group_sid_ptr; @@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, char *end_of_acl = ((char *)pntsd) + acl_len; __u32 dacloffset; - if ((inode == NULL) || (pntsd == NULL)) + if (pntsd == NULL) return -EIO; owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + @@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, if (dacloffset) parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, - group_sid_ptr, inode); + group_sid_ptr, fattr); else cFYI(1, ("no ACL")); /* BB grant all or default perms? */ @@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, sizeof(struct cifs_sid)); */ - return 0; } @@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, } /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ -void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, - const char *path, const __u16 *pfid) +void +cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + struct inode *inode, const char *path, const __u16 *pfid) { struct cifs_ntsd *pntsd = NULL; u32 acllen = 0; @@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ if (pntsd) - rc = parse_sec_desc(pntsd, acllen, inode); + rc = parse_sec_desc(pntsd, acllen, fattr); if (rc) cFYI(1, ("parse sec desc failed rc = %d", rc)); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e6435cba81132..8bcf5a4bcded3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -479,6 +479,8 @@ struct dfs_info3_param { */ #define CIFS_FATTR_DFS_REFERRAL 0x1 +#define CIFS_FATTR_DELETE_PENDING 0x2 +#define CIFS_FATTR_NEED_REVAL 0x4 struct cifs_fattr { u32 cf_flags; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 37c11c08c5294..da8fbf5659919 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -102,7 +102,6 @@ extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, struct cifs_sb_info *cifs_sb); extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); -extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); extern struct inode *cifs_iget(struct super_block *sb, struct cifs_fattr *fattr); @@ -113,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid); -extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, - const char *path, const __u16 *pfid); +extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, + struct cifs_fattr *fattr, struct inode *inode, + const char *path, const __u16 *pfid); extern int mode_to_acl(struct inode *inode, const char *path, __u64); extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 55b616bb381ef..a807397f444e8 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -82,23 +82,34 @@ void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) { struct cifsInodeInfo *cifs_i = CIFS_I(inode); - unsigned long now = jiffies; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + unsigned long oldtime = cifs_i->time; inode->i_atime = fattr->cf_atime; inode->i_mtime = fattr->cf_mtime; inode->i_ctime = fattr->cf_ctime; - inode->i_mode = fattr->cf_mode; inode->i_rdev = fattr->cf_rdev; inode->i_nlink = fattr->cf_nlink; inode->i_uid = fattr->cf_uid; inode->i_gid = fattr->cf_gid; + /* if dynperm is set, don't clobber existing mode */ + if (inode->i_state & I_NEW || + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) + inode->i_mode = fattr->cf_mode; + cifs_i->cifsAttrs = fattr->cf_cifsattrs; cifs_i->uniqueid = fattr->cf_uniqueid; + if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) + cifs_i->time = 0; + else + cifs_i->time = jiffies; + cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, - cifs_i->time, now)); - cifs_i->time = now; + oldtime, cifs_i->time)); + + cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; /* * Can't safely change the file size here if the client is writing to @@ -219,49 +230,6 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } -/** - * cifs_new inode - create new inode, initialize, and hash it - * @sb - pointer to superblock - * @inum - if valid pointer and serverino is enabled, replace i_ino with val - * - * Create a new inode, initialize it for CIFS and hash it. Returns the new - * inode or NULL if one couldn't be allocated. - * - * If the share isn't mounted with "serverino" or inum is a NULL pointer then - * we'll just use the inode number assigned by new_inode(). Note that this can - * mean i_ino collisions since the i_ino assigned by new_inode is not - * guaranteed to be unique. - */ -struct inode * -cifs_new_inode(struct super_block *sb, __u64 *inum) -{ - struct inode *inode; - - inode = new_inode(sb); - if (inode == NULL) - return NULL; - - /* - * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we - * stop passing inum as ptr. Are there sanity checks we can use to - * ensure that the server is really filling in that field? Also, - * if serverino is disabled, perhaps we should be using iunique()? - */ - if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) - inode->i_ino = (unsigned long) *inum; - - /* - * must set this here instead of cifs_alloc_inode since VFS will - * clobber i_flags - */ - if (sb->s_flags & MS_NOATIME) - inode->i_flags |= S_NOATIME | S_NOCMTIME; - - insert_inode_hash(inode); - - return inode; -} - int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *full_path, struct super_block *sb, int xid) @@ -302,9 +270,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, return rc; } -static int decode_sfu_inode(struct inode *inode, __u64 size, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) +static int +cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, + struct cifs_sb_info *cifs_sb, int xid) { int rc; int oplock = 0; @@ -316,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, pbuf = buf; - if (size == 0) { - inode->i_mode |= S_IFIFO; + fattr->cf_mode &= ~S_IFMT; + + if (fattr->cf_eof == 0) { + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; return 0; - } else if (size < 8) { + } else if (fattr->cf_eof < 8) { + fattr->cf_mode |= S_IFREG; + fattr->cf_dtype = DT_REG; return -EINVAL; /* EOPNOTSUPP? */ } @@ -331,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, if (rc == 0) { int buf_type = CIFS_NO_BUFFER; /* Read header */ - rc = CIFSSMBRead(xid, pTcon, - netfid, + rc = CIFSSMBRead(xid, pTcon, netfid, 24 /* length */, 0 /* offset */, &bytes_read, &pbuf, &buf_type); if ((rc == 0) && (bytes_read >= 8)) { if (memcmp("IntxBLK", pbuf, 8) == 0) { cFYI(1, ("Block device")); - inode->i_mode |= S_IFBLK; + fattr->cf_mode |= S_IFBLK; + fattr->cf_dtype = DT_BLK; if (bytes_read == 24) { /* we have enough to decode dev num */ __u64 mjr; /* major */ __u64 mnr; /* minor */ mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - inode->i_rdev = MKDEV(mjr, mnr); + fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxCHR", pbuf, 8) == 0) { cFYI(1, ("Char device")); - inode->i_mode |= S_IFCHR; + fattr->cf_mode |= S_IFCHR; + fattr->cf_dtype = DT_CHR; if (bytes_read == 24) { /* we have enough to decode dev num */ __u64 mjr; /* major */ __u64 mnr; /* minor */ mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); - inode->i_rdev = MKDEV(mjr, mnr); + fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxLNK", pbuf, 7) == 0) { cFYI(1, ("Symlink")); - inode->i_mode |= S_IFLNK; + fattr->cf_mode |= S_IFLNK; + fattr->cf_dtype = DT_LNK; } else { - inode->i_mode |= S_IFREG; /* file? */ + fattr->cf_mode |= S_IFREG; /* file? */ + fattr->cf_dtype = DT_REG; rc = -EOPNOTSUPP; } } else { - inode->i_mode |= S_IFREG; /* then it is a file */ + fattr->cf_mode |= S_IFREG; /* then it is a file */ + fattr->cf_dtype = DT_REG; rc = -EOPNOTSUPP; /* or some unknown SFU type */ } CIFSSMBClose(xid, pTcon, netfid); @@ -376,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ -static int get_sfu_mode(struct inode *inode, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, int xid) +/* + * Fetch mode bits as provided by SFU. + * + * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? + */ +static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, + struct cifs_sb_info *cifs_sb, int xid) { #ifdef CONFIG_CIFS_XATTR ssize_t rc; @@ -386,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, __u32 mode; rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", - ea_value, 4 /* size of buf */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + ea_value, 4 /* size of buf */, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc < 0) return (int)rc; else if (rc > 3) { mode = le32_to_cpu(*((__le32 *)ea_value)); - inode->i_mode &= ~SFBITS_MASK; - cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); - inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; + fattr->cf_mode &= ~SFBITS_MASK; + cFYI(1, ("special bits 0%o org mode 0%o", mode, + fattr->cf_mode)); + fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; cFYI(1, ("special mode bits 0%o", mode)); - return 0; - } else { - return 0; } + + return 0; #else return -EOPNOTSUPP; #endif } -/* - * Needed to setup inode data for the directory which is the - * junction to the new submount (ie to setup the fake directory - * which represents a DFS referral) - */ -static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, - struct super_block *sb) +/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ +void +cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, + struct cifs_sb_info *cifs_sb, bool adjust_tz) { - memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); - -/* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); - __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); - __u8 pfnd_dat->DeletePending = 0; - __u8 pfnd_data->Directory = 0; - __le32 pfnd_dat->EASize = 0; - __u64 pfnd_dat->IndexNumber = 0; - __u64 pfnd_dat->IndexNumber1 = 0; */ - pfnd_dat->CreationTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastAccessTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->LastWriteTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->ChangeTime = - cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); - pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); - pfnd_dat->NumberOfLinks = cpu_to_le32(2); + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); + if (info->DeletePending) + fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; + + if (info->LastAccessTime) + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + else + fattr->cf_atime = CURRENT_TIME; + + fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); + + if (adjust_tz) { + fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; + fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; + } + + fattr->cf_eof = le64_to_cpu(info->EndOfFile); + fattr->cf_bytes = le64_to_cpu(info->AllocationSize); + + if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { + fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; + fattr->cf_dtype = DT_DIR; + } else { + fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; + fattr->cf_dtype = DT_REG; + } + + /* clear write bits if ATTR_READONLY is set */ + if (fattr->cf_cifsattrs & ATTR_READONLY) + fattr->cf_mode &= ~(S_IWUGO); + + fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); + + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; } int cifs_get_inode_info(struct inode **pinode, const unsigned char *full_path, FILE_ALL_INFO *pfindData, struct super_block *sb, int xid, const __u16 *pfid) { - int rc = 0; - __u32 attr; - struct cifsInodeInfo *cifsInfo; + int rc = 0, tmprc; struct cifsTconInfo *pTcon; - struct inode *inode; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *buf = NULL; bool adjustTZ = false; - bool is_dfs_referral = false; - umode_t default_mode; + struct cifs_fattr fattr; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); @@ -482,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode, adjustTZ = true; } } - /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ - if (rc == -EREMOTE) { - is_dfs_referral = true; - fill_fake_finddata(pfindData, sb); + + if (!rc) { + cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, + cifs_sb, adjustTZ); + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, sb); rc = 0; - } else if (rc) + } else { goto cgii_exit; + } - attr = le32_to_cpu(pfindData->Attributes); - - /* get new inode */ + /* + * If an inode wasn't passed in, then get the inode number + * + * Is an i_ino of zero legal? Can we use that to check if the server + * supports returning inode numbers? Are there other sanity checks we + * can use to ensure that the server is really filling in that field? + * + * We can not use the IndexNumber field by default from Windows or + * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA + * CIFS spec claims that this value is unique within the scope of a + * share, and the windows docs hint that it's actually unique + * per-machine. + * + * There may be higher info levels that work but are there Windows + * server or network appliances for which IndexNumber field is not + * guaranteed unique? + */ if (*pinode == NULL) { - __u64 inode_num; - __u64 *pinum = &inode_num; - - /* Is an i_ino of zero legal? Can we use that to check - if the server supports returning inode numbers? Are - there other sanity checks we can use to ensure that - the server is really filling in that field? */ - - /* We can not use the IndexNumber field by default from - Windows or Samba (in ALL_INFO buf) but we can request - it explicitly. It may not be unique presumably if - the server has multiple devices mounted under one share */ - - /* There may be higher info levels that work but are - there Windows server or network appliances for which - IndexNumber field is not guaranteed unique? */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { int rc1 = 0; rc1 = CIFSGetSrvInodeNumber(xid, pTcon, - full_path, pinum, + full_path, &fattr.cf_uniqueid, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc1) { - cFYI(1, ("GetSrvInodeNum rc %d", rc1)); - pinum = NULL; /* BB EOPNOSUPP disable SERVER_INUM? */ + cFYI(1, ("GetSrvInodeNum rc %d", rc1)); + fattr.cf_uniqueid = iunique(sb, ROOT_I); } } else { - pinum = NULL; + fattr.cf_uniqueid = iunique(sb, ROOT_I); } - - *pinode = cifs_new_inode(sb, pinum); - if (*pinode == NULL) { - rc = -ENOMEM; - goto cgii_exit; - } - } - inode = *pinode; - cifsInfo = CIFS_I(inode); - cifsInfo->cifsAttrs = attr; - cifsInfo->delete_pending = pfindData->DeletePending ? true : false; - cFYI(1, ("Old time %ld", cifsInfo->time)); - cifsInfo->time = jiffies; - cFYI(1, ("New time %ld", cifsInfo->time)); - - /* blksize needs to be multiple of two. So safer to default to - blksize and blkbits set in superblock so 2**blkbits and blksize - will match rather than setting to: - (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ - - /* Linux can not store file creation time so ignore it */ - if (pfindData->LastAccessTime) - inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); - else /* do not need to use current_fs_time - time not stored */ - inode->i_atime = CURRENT_TIME; - inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); - inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); - cFYI(DBG2, ("Attributes came in as 0x%x", attr)); - if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { - inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; - inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; - } - - /* get default inode mode */ - if (attr & ATTR_DIRECTORY) - default_mode = cifs_sb->mnt_dir_mode; - else - default_mode = cifs_sb->mnt_file_mode; - - /* set permission bits */ - if (atomic_read(&cifsInfo->inUse) == 0 || - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) - inode->i_mode = default_mode; - else { - /* just reenable write bits if !ATTR_READONLY */ - if ((inode->i_mode & S_IWUGO) == 0 && - (attr & ATTR_READONLY) == 0) - inode->i_mode |= (S_IWUGO & default_mode); - - inode->i_mode &= ~S_IFMT; - } - /* clear write bits if ATTR_READONLY is set */ - if (attr & ATTR_READONLY) - inode->i_mode &= ~S_IWUGO; - - /* set inode type */ - if ((attr & ATTR_SYSTEM) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { - /* no need to fix endianness on 0 */ - if (pfindData->EndOfFile == 0) - inode->i_mode |= S_IFIFO; - else if (decode_sfu_inode(inode, - le64_to_cpu(pfindData->EndOfFile), - full_path, cifs_sb, xid)) - cFYI(1, ("unknown SFU file type\n")); } else { - if (attr & ATTR_DIRECTORY) - inode->i_mode |= S_IFDIR; - else - inode->i_mode |= S_IFREG; + fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; } - cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); - spin_lock(&inode->i_lock); - if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { - /* can not safely shrink the file size here if the - client is writing to it due to potential races */ - i_size_write(inode, cifsInfo->server_eof); - - /* 512 bytes (2**9) is the fake blocksize that must be - used for this calculation */ - inode->i_blocks = (512 - 1 + le64_to_cpu( - pfindData->AllocationSize)) >> 9; + /* query for SFU type info if supported and needed */ + if (fattr.cf_cifsattrs & ATTR_SYSTEM && + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); + if (tmprc) + cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); } - spin_unlock(&inode->i_lock); - inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); - - /* BB fill in uid and gid here? with help from winbind? - or retrieve from NTFS stream extended attribute */ #ifdef CONFIG_CIFS_EXPERIMENTAL /* fill in 0777 bits from ACL */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { cFYI(1, ("Getting mode bits from ACL")); - acl_to_uid_mode(cifs_sb, inode, full_path, pfid); + cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); } #endif - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - /* fill in remaining high mode bits e.g. SUID, VTX */ - get_sfu_mode(inode, full_path, cifs_sb, xid); - } else if (atomic_read(&cifsInfo->inUse) == 0) { - inode->i_uid = cifs_sb->mnt_uid; - inode->i_gid = cifs_sb->mnt_gid; - /* set so we do not keep refreshing these fields with - bad data after user has changed them in memory */ - atomic_set(&cifsInfo->inUse, 1); - } - - cifs_set_ops(inode, is_dfs_referral); - + /* fill in remaining high mode bits e.g. SUID, VTX */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) + cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); + if (!*pinode) { + *pinode = cifs_iget(sb, &fattr); + if (!*pinode) + rc = -ENOMEM; + } else { + cifs_fattr_to_inode(*pinode, &fattr); + } cgii_exit: kfree(buf); @@ -753,21 +665,14 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) return ERR_PTR(-ENOMEM); xid = GetXid(); - if (cifs_sb->tcon->unix_ext) { + if (cifs_sb->tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); - if (!inode) - return ERR_PTR(-ENOMEM); - } else { - inode = iget_locked(sb, ino); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - - rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, + else + rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - unlock_new_inode(inode); - } + + if (!inode) + return ERR_PTR(-ENOMEM); if (rc && cifs_sb->tcon->ipc) { cFYI(1, ("ipc connection - fake read inode")); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 231aa6953f834..f823a4a208a71 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -112,239 +112,74 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, return dentry; } -/* Returns 1 if new inode created, 2 if both dentry and inode were */ -/* Might check in the future if inode number changed so we can rehash inode */ -static int -construct_dentry(struct qstr *qstring, struct file *file, - struct inode **ptmp_inode, struct dentry **pnew_dentry, - __u64 *inum) +static void +cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) { - struct dentry *tmp_dentry = NULL; - struct super_block *sb = file->f_path.dentry->d_sb; - int rc = 0; + fattr->cf_uid = cifs_sb->mnt_uid; + fattr->cf_gid = cifs_sb->mnt_gid; - cFYI(1, ("For %s", qstring->name)); - - tmp_dentry = d_lookup(file->f_path.dentry, qstring); - if (tmp_dentry) { - /* BB: overwrite old name? i.e. tmp_dentry->d_name and - * tmp_dentry->d_name.len?? - */ - cFYI(0, ("existing dentry with inode 0x%p", - tmp_dentry->d_inode)); - *ptmp_inode = tmp_dentry->d_inode; - if (*ptmp_inode == NULL) { - *ptmp_inode = cifs_new_inode(sb, inum); - if (*ptmp_inode == NULL) - return rc; - rc = 1; - } + if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { + fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; + fattr->cf_dtype = DT_DIR; } else { - tmp_dentry = d_alloc(file->f_path.dentry, qstring); - if (tmp_dentry == NULL) { - cERROR(1, ("Failed allocating dentry")); - *ptmp_inode = NULL; - return rc; - } - - if (CIFS_SB(sb)->tcon->nocase) - tmp_dentry->d_op = &cifs_ci_dentry_ops; - else - tmp_dentry->d_op = &cifs_dentry_ops; - - *ptmp_inode = cifs_new_inode(sb, inum); - if (*ptmp_inode == NULL) - return rc; - rc = 2; - } - - tmp_dentry->d_time = jiffies; - *pnew_dentry = tmp_dentry; - return rc; -} - -static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, - char *buf, unsigned int *pobject_type, int isNewInode) -{ - loff_t local_size; - struct timespec local_mtime; - - struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); - struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); - __u32 attr; - __u64 allocation_size; - __u64 end_of_file; - umode_t default_mode; - - /* save mtime and size */ - local_mtime = tmp_inode->i_mtime; - local_size = tmp_inode->i_size; - - if (new_buf_type) { - FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; - - attr = le32_to_cpu(pfindData->ExtFileAttributes); - allocation_size = le64_to_cpu(pfindData->AllocationSize); - end_of_file = le64_to_cpu(pfindData->EndOfFile); - tmp_inode->i_atime = - cifs_NTtimeToUnix(pfindData->LastAccessTime); - tmp_inode->i_mtime = - cifs_NTtimeToUnix(pfindData->LastWriteTime); - tmp_inode->i_ctime = - cifs_NTtimeToUnix(pfindData->ChangeTime); - } else { /* legacy, OS2 and DOS style */ - int offset = cifs_sb->tcon->ses->server->timeAdj; - FIND_FILE_STANDARD_INFO *pfindData = - (FIND_FILE_STANDARD_INFO *)buf; - - tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate, - pfindData->LastWriteTime, - offset); - tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate, - pfindData->LastAccessTime, - offset); - tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate, - pfindData->LastWriteTime, - offset); - attr = le16_to_cpu(pfindData->Attributes); - allocation_size = le32_to_cpu(pfindData->AllocationSize); - end_of_file = le32_to_cpu(pfindData->DataSize); - } - - /* Linux can not store file creation time unfortunately so ignore it */ - - cifsInfo->cifsAttrs = attr; -#ifdef CONFIG_CIFS_EXPERIMENTAL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - /* get more accurate mode via ACL - so force inode refresh */ - cifsInfo->time = 0; - } else -#endif /* CONFIG_CIFS_EXPERIMENTAL */ - cifsInfo->time = jiffies; - - /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ - /* 2767 perms - indicate mandatory locking */ - /* BB fill in uid and gid here? with help from winbind? - or retrieve from NTFS stream extended attribute */ - if (atomic_read(&cifsInfo->inUse) == 0) { - tmp_inode->i_uid = cifs_sb->mnt_uid; - tmp_inode->i_gid = cifs_sb->mnt_gid; + fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; + fattr->cf_dtype = DT_REG; } - if (attr & ATTR_DIRECTORY) - default_mode = cifs_sb->mnt_dir_mode; - else - default_mode = cifs_sb->mnt_file_mode; - - /* set initial permissions */ - if ((atomic_read(&cifsInfo->inUse) == 0) || - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) - tmp_inode->i_mode = default_mode; - else { - /* just reenable write bits if !ATTR_READONLY */ - if ((tmp_inode->i_mode & S_IWUGO) == 0 && - (attr & ATTR_READONLY) == 0) - tmp_inode->i_mode |= (S_IWUGO & default_mode); - - tmp_inode->i_mode &= ~S_IFMT; - } - - /* clear write bits if ATTR_READONLY is set */ - if (attr & ATTR_READONLY) - tmp_inode->i_mode &= ~S_IWUGO; + if (fattr->cf_cifsattrs & ATTR_READONLY) + fattr->cf_mode &= ~S_IWUGO; - /* set inode type */ - if ((attr & ATTR_SYSTEM) && - (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { - if (end_of_file == 0) { - tmp_inode->i_mode |= S_IFIFO; - *pobject_type = DT_FIFO; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && + fattr->cf_cifsattrs & ATTR_SYSTEM) { + if (fattr->cf_eof == 0) { + fattr->cf_mode &= ~S_IFMT; + fattr->cf_mode |= S_IFIFO; + fattr->cf_dtype = DT_FIFO; } else { /* - * trying to get the type can be slow, so just call - * this a regular file for now, and mark for reval + * trying to get the type and mode via SFU can be slow, + * so just call those regular files for now, and mark + * for reval */ - tmp_inode->i_mode |= S_IFREG; - *pobject_type = DT_REG; - cifsInfo->time = 0; - } - } else { - if (attr & ATTR_DIRECTORY) { - tmp_inode->i_mode |= S_IFDIR; - *pobject_type = DT_DIR; - } else { - tmp_inode->i_mode |= S_IFREG; - *pobject_type = DT_REG; + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; } } +} - /* can not fill in nlink here as in qpathinfo version and Unx search */ - if (atomic_read(&cifsInfo->inUse) == 0) - atomic_set(&cifsInfo->inUse, 1); +void +cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, + struct cifs_sb_info *cifs_sb) +{ + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); + fattr->cf_eof = le64_to_cpu(info->EndOfFile); + fattr->cf_bytes = le64_to_cpu(info->AllocationSize); + fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); + fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); + fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); + + cifs_fill_common_info(fattr, cifs_sb); +} - cifsInfo->server_eof = end_of_file; - spin_lock(&tmp_inode->i_lock); - if (is_size_safe_to_change(cifsInfo, end_of_file)) { - /* can not safely change the file size here if the - client is writing to it due to potential races */ - i_size_write(tmp_inode, end_of_file); +void +cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, + struct cifs_sb_info *cifs_sb) +{ + int offset = cifs_sb->tcon->ses->server->timeAdj; - /* 512 bytes (2**9) is the fake blocksize that must be used */ - /* for this calculation, even though the reported blocksize is larger */ - tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; - } - spin_unlock(&tmp_inode->i_lock); - - if (allocation_size < end_of_file) - cFYI(1, ("May be sparse file, allocation less than file size")); - cFYI(1, ("File Size %ld and blocks %llu", - (unsigned long)tmp_inode->i_size, - (unsigned long long)tmp_inode->i_blocks)); - if (S_ISREG(tmp_inode->i_mode)) { - cFYI(1, ("File inode")); - tmp_inode->i_op = &cifs_file_inode_ops; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_direct_ops; - } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) - tmp_inode->i_fop = &cifs_file_nobrl_ops; - else - tmp_inode->i_fop = &cifs_file_ops; - - if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && - (cifs_sb->tcon->ses->server->maxBuf < - PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) - tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; - else - tmp_inode->i_data.a_ops = &cifs_addr_ops; - - if (isNewInode) - return; /* No sense invalidating pages for new inode - since have not started caching readahead file - data yet */ - - if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && - (local_size == tmp_inode->i_size)) { - cFYI(1, ("inode exists but unchanged")); - } else { - /* file may have changed on server */ - cFYI(1, ("invalidate inode, readdir detected change")); - invalidate_remote_inode(tmp_inode); - } - } else if (S_ISDIR(tmp_inode->i_mode)) { - cFYI(1, ("Directory inode")); - tmp_inode->i_op = &cifs_dir_inode_ops; - tmp_inode->i_fop = &cifs_dir_ops; - } else if (S_ISLNK(tmp_inode->i_mode)) { - cFYI(1, ("Symbolic Link inode")); - tmp_inode->i_op = &cifs_symlink_inode_ops; - } else { - cFYI(1, ("Init special inode")); - init_special_inode(tmp_inode, tmp_inode->i_mode, - tmp_inode->i_rdev); - } + memset(fattr, 0, sizeof(*fattr)); + fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, + info->LastAccessTime, offset); + fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, + info->LastWriteTime, offset); + fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, + info->LastWriteTime, offset); + + fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); + fattr->cf_bytes = le32_to_cpu(info->AllocationSize); + fattr->cf_eof = le32_to_cpu(info->DataSize); + + cifs_fill_common_info(fattr, cifs_sb); } /* BB eventually need to add the following helper function to @@ -846,11 +681,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, int rc = 0; struct qstr qstring; struct cifsFileInfo *pCifsF; - unsigned int obj_type; - __u64 inum; + u64 inum; ino_t ino; + struct super_block *sb; struct cifs_sb_info *cifs_sb; - struct inode *tmp_inode; struct dentry *tmp_dentry; struct cifs_fattr fattr; @@ -870,71 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, if (rc != 0) return 0; - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + sb = file->f_path.dentry->d_sb; + cifs_sb = CIFS_SB(sb); qstring.name = scratch_buf; rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, pCifsF->srch_inf.info_level, pCifsF->srch_inf.unicode, cifs_sb, - max_len, - &inum /* returned */); + max_len, &inum /* returned */); if (rc) return rc; - /* only these two infolevels return valid inode numbers */ - if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) cifs_unix_basic_to_fattr(&fattr, &((FILE_UNIX_INFO *) pfindEntry)->basic, cifs_sb); - tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, - &fattr); - obj_type = fattr.cf_dtype; - ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); - } else { - if (pCifsF->srch_inf.info_level == - SMB_FIND_FILE_ID_FULL_DIR_INFO) - rc = construct_dentry(&qstring, file, &tmp_inode, - &tmp_dentry, &inum); - else - rc = construct_dentry(&qstring, file, &tmp_inode, - &tmp_dentry, NULL); - - if ((tmp_inode == NULL) || (tmp_dentry == NULL)) { - rc = -ENOMEM; - goto out; - } - - /* we pass in rc below, indicating whether it is a new inode, - * so we can figure out whether to invalidate the inode cached - * data if the file has changed - */ - if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) - fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc); - else - fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc); + else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) + cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) + pfindEntry, cifs_sb); + else + cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) + pfindEntry, cifs_sb); - /* new inode - needs to be tied to dentry */ - if (rc) { - d_instantiate(tmp_dentry, tmp_inode); - if (rc == 2) - d_rehash(tmp_dentry); - } + /* FIXME: make _to_fattr functions fill this out */ + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) + fattr.cf_uniqueid = inum; + else + fattr.cf_uniqueid = iunique(sb, ROOT_I); - ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); - } + ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); + tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, - ino, obj_type); + ino, fattr.cf_dtype); + + /* + * we can not return filldir errors to the caller since they are + * "normal" when the stat blocksize is too small - we return remapped + * error instead + * + * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above + * case already. Why should we be clobbering other errors from it? + */ if (rc) { cFYI(1, ("filldir rc = %d", rc)); - /* we can not return filldir errors to the caller - since they are "normal" when the stat blocksize - is too small - we return remapped error instead */ rc = -EOVERFLOW; } - -out: dput(tmp_dentry); return rc; } -- GitLab From aeaaf253c4dee7ff9af2f3f0595f3bb66964e944 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 01:46:39 -0400 Subject: [PATCH 0905/1002] cifs: remove cifsInodeInfo->inUse counter cifs: remove cifsInodeInfo->inUse counter It was purported to be a refcounter of some sort, but was never used that way. It never served any purpose that wasn't served equally well by the I_NEW flag. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/cifsfs.c | 1 - fs/cifs/cifsglob.h | 1 - 2 files changed, 2 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9f669f982c4d4..44f30504b82d1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -308,7 +308,6 @@ cifs_alloc_inode(struct super_block *sb) if (!cifs_inode) return NULL; cifs_inode->cifsAttrs = 0x20; /* default */ - atomic_set(&cifs_inode->inUse, 0); cifs_inode->time = 0; cifs_inode->write_behind_rc = 0; /* Until the file is open and we have gotten oplock diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 8bcf5a4bcded3..63f6cdfa56387 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -364,7 +364,6 @@ struct cifsInodeInfo { struct list_head openFileList; int write_behind_rc; __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ - atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ unsigned long time; /* jiffies of last update/check of inode */ bool clientCanCacheRead:1; /* read oplock */ bool clientCanCacheAll:1; /* read and writebehind oplock */ -- GitLab From d0c280d26de9422c9c943f8f486b9830cd9bea70 Mon Sep 17 00:00:00 2001 From: Jeff Layton <jlayton@redhat.com> Date: Thu, 9 Jul 2009 01:46:44 -0400 Subject: [PATCH 0906/1002] cifs: when ATTR_READONLY is set, only clear write bits on non-directories cifs: when ATTR_READONLY is set, only clear write bits on non-directories On windows servers, ATTR_READONLY apparently either has no meaning or serves as some sort of queue to certain applications for unrelated behavior. This MS kbase article has details: http://support.microsoft.com/kb/326549/ Don't clear the write bits directory mode when ATTR_READONLY is set. Reported-by: pouchat@peewiki.net Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com> --- fs/cifs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a807397f444e8..18afe57b24611 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -419,11 +419,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, } else { fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; fattr->cf_dtype = DT_REG; - } - /* clear write bits if ATTR_READONLY is set */ - if (fattr->cf_cifsattrs & ATTR_READONLY) - fattr->cf_mode &= ~(S_IWUGO); + /* clear write bits if ATTR_READONLY is set */ + if (fattr->cf_cifsattrs & ATTR_READONLY) + fattr->cf_mode &= ~(S_IWUGO); + } fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); -- GitLab From a57de0b4336e48db2811a2030bb68dba8dd09d88 Mon Sep 17 00:00:00 2001 From: Jiri Olsa <jolsa@redhat.com> Date: Wed, 8 Jul 2009 12:09:13 +0000 Subject: [PATCH 0907/1002] net: adding memory barrier to the poll and receive callbacks Adding memory barrier after the poll_wait function, paired with receive callbacks. Adding fuctions sock_poll_wait and sk_has_sleeper to wrap the memory barrier. Without the memory barrier, following race can happen. The race fires, when following code paths meet, and the tp->rcv_nxt and __add_wait_queue updates stay in CPU caches. CPU1 CPU2 sys_select receive packet ... ... __add_wait_queue update tp->rcv_nxt ... ... tp->rcv_nxt check sock_def_readable ... { schedule ... if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible(sk->sk_sleep) ... } If there was no cache the code would work ok, since the wait_queue and rcv_nxt are opposit to each other. Meaning that once tp->rcv_nxt is updated by CPU2, the CPU1 either already passed the tp->rcv_nxt check and sleeps, or will get the new value for tp->rcv_nxt and will return with new data mask. In both cases the process (CPU1) is being added to the wait queue, so the waitqueue_active (CPU2) call cannot miss and will wake up CPU1. The bad case is when the __add_wait_queue changes done by CPU1 stay in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 will then endup calling schedule and sleep forever if there are no more data on the socket. Calls to poll_wait in following modules were ommited: net/bluetooth/af_bluetooth.c net/irda/af_irda.c net/irda/irnet/irnet_ppp.c net/mac80211/rc80211_pid_debugfs.c net/phonet/socket.c net/rds/af_rds.c net/rfkill/core.c net/sunrpc/cache.c net/sunrpc/rpc_pipe.c net/tipc/socket.c Signed-off-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- include/net/sock.h | 66 ++++++++++++++++++++++++++++++++++++++++++++ net/atm/common.c | 6 ++-- net/core/datagram.c | 2 +- net/core/sock.c | 8 +++--- net/dccp/output.c | 2 +- net/dccp/proto.c | 2 +- net/ipv4/tcp.c | 2 +- net/iucv/af_iucv.c | 4 +-- net/rxrpc/af_rxrpc.c | 4 +-- net/unix/af_unix.c | 8 +++--- 10 files changed, 85 insertions(+), 19 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 352f06bbd7a9b..4eb8409249f6d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -54,6 +54,7 @@ #include <linux/filter.h> #include <linux/rculist_nulls.h> +#include <linux/poll.h> #include <asm/atomic.h> #include <net/dst.h> @@ -1241,6 +1242,71 @@ static inline int sk_has_allocations(const struct sock *sk) return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk); } +/** + * sk_has_sleeper - check if there are any waiting processes + * @sk: socket + * + * Returns true if socket has waiting processes + * + * The purpose of the sk_has_sleeper and sock_poll_wait is to wrap the memory + * barrier call. They were added due to the race found within the tcp code. + * + * Consider following tcp code paths: + * + * CPU1 CPU2 + * + * sys_select receive packet + * ... ... + * __add_wait_queue update tp->rcv_nxt + * ... ... + * tp->rcv_nxt check sock_def_readable + * ... { + * schedule ... + * if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + * wake_up_interruptible(sk->sk_sleep) + * ... + * } + * + * The race for tcp fires when the __add_wait_queue changes done by CPU1 stay + * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 + * could then endup calling schedule and sleep forever if there are no more + * data on the socket. + */ +static inline int sk_has_sleeper(struct sock *sk) +{ + /* + * We need to be sure we are in sync with the + * add_wait_queue modifications to the wait queue. + * + * This memory barrier is paired in the sock_poll_wait. + */ + smp_mb(); + return sk->sk_sleep && waitqueue_active(sk->sk_sleep); +} + +/** + * sock_poll_wait - place memory barrier behind the poll_wait call. + * @filp: file + * @wait_address: socket wait queue + * @p: poll_table + * + * See the comments in the sk_has_sleeper function. + */ +static inline void sock_poll_wait(struct file *filp, + wait_queue_head_t *wait_address, poll_table *p) +{ + if (p && wait_address) { + poll_wait(filp, wait_address, p); + /* + * We need to be sure we are in sync with the + * socket flags modification. + * + * This memory barrier is paired in the sk_has_sleeper. + */ + smp_mb(); + } +} + /* * Queue a received datagram if it will fit. Stream and sequenced * protocols can't normally use this as they need to fit buffers in diff --git a/net/atm/common.c b/net/atm/common.c index c1c97936192c7..8c4d843eb17f4 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -92,7 +92,7 @@ static void vcc_sock_destruct(struct sock *sk) static void vcc_def_wakeup(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up(sk->sk_sleep); read_unlock(&sk->sk_callback_lock); } @@ -110,7 +110,7 @@ static void vcc_write_space(struct sock *sk) read_lock(&sk->sk_callback_lock); if (vcc_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); @@ -594,7 +594,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) struct atm_vcc *vcc; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; vcc = ATM_SD(sock); diff --git a/net/core/datagram.c b/net/core/datagram.c index 58abee1f1df1b..b0fe69211eefe 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -712,7 +712,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ diff --git a/net/core/sock.c b/net/core/sock.c index b0ba569bc9736..6354863b1c687 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1715,7 +1715,7 @@ EXPORT_SYMBOL(sock_no_sendpage); static void sock_def_wakeup(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_all(sk->sk_sleep); read_unlock(&sk->sk_callback_lock); } @@ -1723,7 +1723,7 @@ static void sock_def_wakeup(struct sock *sk) static void sock_def_error_report(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_poll(sk->sk_sleep, POLLERR); sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); read_unlock(&sk->sk_callback_lock); @@ -1732,7 +1732,7 @@ static void sock_def_error_report(struct sock *sk) static void sock_def_readable(struct sock *sk, int len) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); @@ -1747,7 +1747,7 @@ static void sock_def_write_space(struct sock *sk) * progress. --DaveM */ if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND); diff --git a/net/dccp/output.c b/net/dccp/output.c index c0e88c16d0888..c96119fda6885 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -196,7 +196,7 @@ void dccp_write_space(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 314a1b5c033c8..94ca8eaace7d0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -311,7 +311,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, unsigned int mask; struct sock *sk = sock->sk; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == DCCP_LISTEN) return inet_csk_listen_poll(sk); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7870a535dac64..91145244ea630 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -339,7 +339,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) struct sock *sk = sock->sk; struct tcp_sock *tp = tcp_sk(sk); - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == TCP_LISTEN) return inet_csk_listen_poll(sk); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 6be5f92d10943..49c15b48408e5 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -306,7 +306,7 @@ static inline int iucv_below_msglim(struct sock *sk) static void iucv_sock_wake_msglim(struct sock *sk) { read_lock(&sk->sk_callback_lock); - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_all(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); read_unlock(&sk->sk_callback_lock); @@ -1256,7 +1256,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk; unsigned int mask = 0; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); if (sk->sk_state == IUCV_LISTEN) return iucv_accept_poll(sk); diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index eac5e7bb73659..bfe493ebf27c3 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -63,7 +63,7 @@ static void rxrpc_write_space(struct sock *sk) _enter("%p", sk); read_lock(&sk->sk_callback_lock); if (rxrpc_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } @@ -588,7 +588,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, unsigned int mask; struct sock *sk = sock->sk; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* the socket is readable if there are any messages waiting on the Rx diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 36d4e44d62334..fc3ebb906911b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk) { read_lock(&sk->sk_callback_lock); if (unix_writable(sk)) { - if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + if (sk_has_sleeper(sk)) wake_up_interruptible_sync(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); } @@ -1985,7 +1985,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table struct sock *sk = sock->sk; unsigned int mask; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ @@ -2022,7 +2022,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, struct sock *sk = sock->sk, *other; unsigned int mask, writable; - poll_wait(file, sk->sk_sleep, wait); + sock_poll_wait(file, sk->sk_sleep, wait); mask = 0; /* exceptional events? */ @@ -2053,7 +2053,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, other = unix_peer_get(sk); if (other) { if (unix_peer(other) != sk) { - poll_wait(file, &unix_sk(other)->peer_wait, + sock_poll_wait(file, &unix_sk(other)->peer_wait, wait); if (unix_recvq_full(other)) writable = 0; -- GitLab From ad46276952f1af34cd91d46d49ba13d347d56367 Mon Sep 17 00:00:00 2001 From: Jiri Olsa <jolsa@redhat.com> Date: Wed, 8 Jul 2009 12:10:31 +0000 Subject: [PATCH 0908/1002] memory barrier: adding smp_mb__after_lock Adding smp_mb__after_lock define to be used as a smp_mb call after a lock. Making it nop for x86, since {read|write|spin}_lock() on x86 are full memory barriers. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- arch/x86/include/asm/spinlock.h | 4 ++++ include/linux/spinlock.h | 5 +++++ include/net/sock.h | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index b7e5db8763994..4e77853321dbc 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -302,4 +302,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) #define _raw_read_relax(lock) cpu_relax() #define _raw_write_relax(lock) cpu_relax() +/* The {read|write|spin}_lock() on x86 are full memory barriers. */ +static inline void smp_mb__after_lock(void) { } +#define ARCH_HAS_SMP_MB_AFTER_LOCK + #endif /* _ASM_X86_SPINLOCK_H */ diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 252b245cfcf4c..4be57ab03478c 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -132,6 +132,11 @@ do { \ #endif /*__raw_spin_is_contended*/ #endif +/* The lock does not imply full memory barrier. */ +#ifndef ARCH_HAS_SMP_MB_AFTER_LOCK +static inline void smp_mb__after_lock(void) { smp_mb(); } +#endif + /** * spin_unlock_wait - wait until the spinlock gets unlocked * @lock: the spinlock in question. diff --git a/include/net/sock.h b/include/net/sock.h index 4eb8409249f6d..2c0da9239b959 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1271,6 +1271,9 @@ static inline int sk_has_allocations(const struct sock *sk) * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 * could then endup calling schedule and sleep forever if there are no more * data on the socket. + * + * The sk_has_sleeper is always called right after a call to read_lock, so we + * can use smp_mb__after_lock barrier. */ static inline int sk_has_sleeper(struct sock *sk) { @@ -1280,7 +1283,7 @@ static inline int sk_has_sleeper(struct sock *sk) * * This memory barrier is paired in the sock_poll_wait. */ - smp_mb(); + smp_mb__after_lock(); return sk->sk_sleep && waitqueue_active(sk->sk_sleep); } -- GitLab From 8faa2a786a5337683109d77ccf880339fdcdb332 Mon Sep 17 00:00:00 2001 From: Yi Zou <yi.zou@intel.com> Date: Thu, 9 Jul 2009 02:29:50 +0000 Subject: [PATCH 0909/1002] ixgbe: Fix coexistence of FCoE and Flow Director in 82599 Fix coexistence of Fiber Channel over Ethernet (FCoE) and Flow Director (FDIR) in 82599 and remove the disabling of FDIR when FCoE is enabled. Currently, FDIR is turned off when FCoE is enabled under the assumption that FCoE is always enabled with DCB being turned on. However, FDIR does not have to be turned off all the time when FCoE is enabled since FCoE can be enabled without DCB being turned on, e.g., use link pause only. This patch makes sure that when DCB is turned on or off, FDIR is turned on or off correspondingly; and when FCoE is enabled, it does not disable FDIR, rather, it will have FDIR set up properly so FCoE and FDIR can coexist regardless of DCB being on or off. Signed-off-by: Yi Zou <yi.zou@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/ixgbe/ixgbe_dcb_nl.c | 6 ++++++ drivers/net/ixgbe/ixgbe_main.c | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index d56890f5c9d53..7c5978ad929ad 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -138,6 +138,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->hw.fc.requested_mode = ixgbe_fc_none; } adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + } adapter->flags |= IXGBE_FLAG_DCB_ENABLED; ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) @@ -154,6 +158,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state) adapter->dcb_cfg.pfc_mode_enable = false; adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) netdev->netdev_ops->ndo_open(netdev); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a3061aacffd84..e3442f47f932a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3130,7 +3130,11 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) #endif if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n"); - ixgbe_set_rss_queues(adapter); + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) + ixgbe_set_fdir_queues(adapter); + else + ixgbe_set_rss_queues(adapter); } /* adding FCoE rx rings to the end */ f->mask = adapter->num_rx_queues; @@ -3388,7 +3392,12 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) } #endif /* CONFIG_IXGBE_DCB */ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { - ixgbe_cache_ring_rss(adapter); + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || + (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) + ixgbe_cache_ring_fdir(adapter); + else + ixgbe_cache_ring_rss(adapter); + fcoe_i = f->mask; } for (i = 0; i < f->indices; i++, fcoe_i++) @@ -5578,12 +5587,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->features |= NETIF_F_FCOE_CRC; netdev->features |= NETIF_F_FSO; netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; - DPRINTK(DRV, INFO, "FCoE enabled, " - "disabling Flow Director\n"); - adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; - adapter->flags &= - ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; - adapter->atr_sample_rate = 0; } else { adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; } -- GitLab From e594e96e8a14101a6decabf6746bd5186287debc Mon Sep 17 00:00:00 2001 From: Roland Dreier <rdreier@cisco.com> Date: Thu, 9 Jul 2009 09:30:25 +0000 Subject: [PATCH 0910/1002] cxgb3: Fix crash caused by stashing wrong netdev_queue Commit c3a8c5b6 ("cxgb3: move away from LLTX") exposed a bug in how cxgb3 looks up the netdev_queue it stashes away in a qset during initialization. For multiport devices, the TX queue index it uses is offset by the first_qset index of each port. This leads to a crash once LLTX is removed, since hard_start_xmit is called with one TX queue lock held, while the TX reclaim timer task grabs a different (wrong) TX queue lock when it frees skbs. Fix this by removing the first_qset offset used to look up the TX queue passed into t3_sge_alloc_qset() from setup_sge_qsets(). Signed-off-by: Roland Dreier <rolandd@cisco.com> Acked-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net> --- drivers/net/cxgb3/cxgb3_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 538dda4422dca..fb5df5c6203e9 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -642,8 +642,7 @@ static int setup_sge_qsets(struct adapter *adap) struct port_info *pi = netdev_priv(dev); pi->qs = &adap->sge.qs[pi->first_qset]; - for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; - ++j, ++qset_idx) { + for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO); err = t3_sge_alloc_qset(adap, qset_idx, 1, (adap->flags & USING_MSIX) ? qset_idx + 1 : -- GitLab From 8d7ff4f2a0b22b7d6d7bc3982257d1dadea22824 Mon Sep 17 00:00:00 2001 From: Robert Richter <robert.richter@amd.com> Date: Tue, 23 Jun 2009 11:48:14 +0200 Subject: [PATCH 0911/1002] x86/oprofile: rename kernel parameter for architectural perfmon to arch_perfmon The short name of the achitecture is 'arch_perfmon'. This patch changes the kernel parameter to use this name. Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Robert Richter <robert.richter@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- Documentation/kernel-parameters.txt | 4 ++-- arch/x86/oprofile/nmi_int.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 92e1ab8178a86..c59e965a748dd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1728,8 +1728,8 @@ and is between 256 and 4096 characters. It is defined in the file oprofile.cpu_type= Force an oprofile cpu type This might be useful if you have an older oprofile userland or if you want common events. - Format: { archperfmon } - archperfmon: [X86] Force use of architectural + Format: { arch_perfmon } + arch_perfmon: [X86] Force use of architectural perfmon on Intel CPUs instead of the CPU specific event set. diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b07dd8d0b321d..89b9a5cd63da1 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -390,7 +390,7 @@ static int __init p4_init(char **cpu_type) static int force_arch_perfmon; static int force_cpu_type(const char *str, struct kernel_param *kp) { - if (!strcmp(str, "archperfmon")) { + if (!strcmp(str, "arch_perfmon")) { force_arch_perfmon = 1; printk(KERN_INFO "oprofile: forcing architectural perfmon\n"); } -- GitLab From 42359da44112565e12a5209befb36dc6b6d6cd9c Mon Sep 17 00:00:00 2001 From: Dave Jones <davej@redhat.com> Date: Thu, 9 Jul 2009 21:54:39 -0400 Subject: [PATCH 0912/1002] Fix compile error in bmac.c Looks like the change in ad361c9884e809340f6daca80d56a9e9c871690a wasn't compile tested. Signed-off-by: Dave Jones <davej@redhat.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/net/bmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index a76315dc77678..206144f2470f3 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -431,7 +431,7 @@ bmac_init_phy(struct net_device *dev) printk(KERN_DEBUG); printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr)); } - print(KERN_CONT "\n"); + printk(KERN_CONT "\n"); if (bp->is_bmac_plus) { unsigned int capable, ctrl; -- GitLab From afecb0d02ad5554cb59c2a30c262da200beaa002 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Thu, 9 Jul 2009 20:15:44 +0200 Subject: [PATCH 0913/1002] sm501fb: fix regression with uninitalized fb_info->mm_lock mutex Remove call to the fb_set_par() before the register_framebuffer(). This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/sm501fb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 16d4f4c7d52b5..924d79462780c 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -1540,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb, if (ret) dev_err(info->dev, "check_var() failed on initial setup?\n"); - /* ensure we've activated our new configuration */ - (fb->fbops->fb_set_par)(fb); - return 0; } -- GitLab From 016d3569bf7b21375451d91be6ee2ad4ffff5211 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt <krzysztof.h1@wp.pl> Date: Thu, 9 Jul 2009 20:14:10 +0200 Subject: [PATCH 0914/1002] mx3fb: fix regression with uninitalized fb_info->mm_lock mutex Remove call to the mx3fb_set_par() and the mx3fb_blank() before the register_framebuffer(). This fixes a problem with uninitialized the fb_info->mm_lock mutex introduced by the commit 537a1bf059f " fbdev: add mutex for fb_mmap locking" Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/video/mx3fb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 567fb944bd2ae..f8778cde21832 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1365,11 +1365,6 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) init_completion(&mx3fbi->flip_cmpl); disable_irq(ichan->eof_irq); dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); - ret = mx3fb_set_par(fbi); - if (ret < 0) - goto esetpar; - - mx3fb_blank(FB_BLANK_UNBLANK, fbi); dev_info(dev, "registered, using mode %s\n", fb_mode); -- GitLab From 2b8777ca0c944bf6498c45ed9c5c246bd63a719e Mon Sep 17 00:00:00 2001 From: Maynard Johnson <maynardj@us.ibm.com> Date: Wed, 27 May 2009 10:15:08 -0500 Subject: [PATCH 0915/1002] oprofile: reset bt_lost_no_mapping with other stats The bt_lost_no_mapping is not getting reset at the start of a profiling run, thus the oprofiled.log shows erroneous values for this statistic. The attached patch fixes this problem. Signed-off-by: Maynard Johnson <maynardj@us.ibm.com> Signed-off-by: Robert Richter <robert.richter@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- drivers/oprofile/oprofile_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index e1f6ce03705ed..3c2270a8300c4 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -33,6 +33,7 @@ void oprofile_reset_stats(void) atomic_set(&oprofile_stats.sample_lost_no_mm, 0); atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); atomic_set(&oprofile_stats.event_lost_overflow, 0); + atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); } -- GitLab From 8aa7e847d834ed937a9ad37a0f2ad5b8584c1ab0 Mon Sep 17 00:00:00 2001 From: Jens Axboe <jens.axboe@oracle.com> Date: Thu, 9 Jul 2009 14:52:32 +0200 Subject: [PATCH 0916/1002] Fix congestion_wait() sync/async vs read/write confusion Commit 1faa16d22877f4839bd433547d770c676d1d964c accidentally broke the bdi congestion wait queue logic, causing us to wait on congestion for WRITE (== 1) when we really wanted BLK_RW_ASYNC (== 0) instead. Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- arch/x86/lib/usercopy_32.c | 2 +- drivers/block/pktcdvd.c | 10 ++++++---- drivers/md/dm-crypt.c | 2 +- fs/fat/file.c | 2 +- fs/fuse/dev.c | 8 ++++---- fs/nfs/write.c | 8 +++++--- fs/reiserfs/journal.c | 2 +- fs/xfs/linux-2.6/kmem.c | 4 ++-- fs/xfs/linux-2.6/xfs_buf.c | 2 +- include/linux/backing-dev.h | 6 +++--- include/linux/blkdev.h | 8 ++++---- mm/backing-dev.c | 7 +++---- mm/memcontrol.c | 2 +- mm/page-writeback.c | 8 ++++---- mm/page_alloc.c | 4 ++-- mm/vmscan.c | 8 ++++---- 16 files changed, 43 insertions(+), 40 deletions(-) diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 7c8ca91bb9ecb..1f118d462acc2 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -751,7 +751,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, if (retval == -ENOMEM && is_global_init(current)) { up_read(¤t->mm->mmap_sem); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto survive; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 83650e00632d8..99a506f619b71 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1372,8 +1372,10 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) wakeup = (pd->write_congestion_on > 0 && pd->bio_queue_size <= pd->write_congestion_off); spin_unlock(&pd->lock); - if (wakeup) - clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE); + if (wakeup) { + clear_bdi_congested(&pd->disk->queue->backing_dev_info, + BLK_RW_ASYNC); + } pkt->sleep_time = max(PACKET_WAIT_TIME, 1); pkt_set_state(pkt, PACKET_WAITING_STATE); @@ -2592,10 +2594,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) spin_lock(&pd->lock); if (pd->write_congestion_on > 0 && pd->bio_queue_size >= pd->write_congestion_on) { - set_bdi_congested(&q->backing_dev_info, WRITE); + set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC); do { spin_unlock(&pd->lock); - congestion_wait(WRITE, HZ); + congestion_wait(BLK_RW_ASYNC, HZ); spin_lock(&pd->lock); } while(pd->bio_queue_size > pd->write_congestion_off); } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 9933eb861c719..529e2ba505c30 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -776,7 +776,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) * But don't wait if split was due to the io size restriction */ if (unlikely(out_of_pages)) - congestion_wait(WRITE, HZ/100); + congestion_wait(BLK_RW_ASYNC, HZ/100); /* * With async crypto it is unsafe to share the crypto context diff --git a/fs/fat/file.c b/fs/fat/file.c index b28ea646ff607..f042b965c95c8 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -134,7 +134,7 @@ static int fat_file_release(struct inode *inode, struct file *filp) if ((filp->f_mode & FMODE_WRITE) && MSDOS_SB(inode->i_sb)->options.flush) { fat_flush_inodes(inode->i_sb, inode, NULL); - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } return 0; } diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index f58ecbc416c86..6484eb75acd6f 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -286,8 +286,8 @@ __releases(&fc->lock) } if (fc->num_background == FUSE_CONGESTION_THRESHOLD && fc->connected && fc->bdi_initialized) { - clear_bdi_congested(&fc->bdi, READ); - clear_bdi_congested(&fc->bdi, WRITE); + clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); + clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC); } fc->num_background--; fc->active_background--; @@ -414,8 +414,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, fc->blocked = 1; if (fc->num_background == FUSE_CONGESTION_THRESHOLD && fc->bdi_initialized) { - set_bdi_congested(&fc->bdi, READ); - set_bdi_congested(&fc->bdi, WRITE); + set_bdi_congested(&fc->bdi, BLK_RW_SYNC); + set_bdi_congested(&fc->bdi, BLK_RW_ASYNC); } list_add_tail(&req->list, &fc->bg_queue); flush_bg_queue(fc); diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ce728829f79a5..0a0a2ff767c31 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -202,8 +202,10 @@ static int nfs_set_page_writeback(struct page *page) struct nfs_server *nfss = NFS_SERVER(inode); if (atomic_long_inc_return(&nfss->writeback) > - NFS_CONGESTION_ON_THRESH) - set_bdi_congested(&nfss->backing_dev_info, WRITE); + NFS_CONGESTION_ON_THRESH) { + set_bdi_congested(&nfss->backing_dev_info, + BLK_RW_ASYNC); + } } return ret; } @@ -215,7 +217,7 @@ static void nfs_end_page_writeback(struct page *page) end_page_writeback(page); if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) - clear_bdi_congested(&nfss->backing_dev_info, WRITE); + clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); } /* diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 77f5bb746bf07..90622200b39c0 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -997,7 +997,7 @@ static int reiserfs_async_progress_wait(struct super_block *s) DEFINE_WAIT(wait); struct reiserfs_journal *j = SB_JOURNAL(s); if (atomic_read(&j->j_async_throttle)) - congestion_wait(WRITE, HZ / 10); + congestion_wait(BLK_RW_ASYNC, HZ / 10); return 0; } diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 1cd3b55ee3d22..2d3f90afe5f14 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -53,7 +53,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __func__, lflags); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); } @@ -130,7 +130,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __func__, lflags); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 1418b916fc275..0c93c7ef3d187 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -412,7 +412,7 @@ _xfs_buf_lookup_pages( XFS_STATS_INC(xb_page_retries); xfsbufd_wakeup(0, gfp_mask); - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry; } diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 0ec2c594868e6..3a52a63c1351e 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -229,9 +229,9 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) (1 << BDI_async_congested)); } -void clear_bdi_congested(struct backing_dev_info *bdi, int rw); -void set_bdi_congested(struct backing_dev_info *bdi, int rw); -long congestion_wait(int rw, long timeout); +void clear_bdi_congested(struct backing_dev_info *bdi, int sync); +void set_bdi_congested(struct backing_dev_info *bdi, int sync); +long congestion_wait(int sync, long timeout); static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 49ae07951d554..bb3d399787013 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -779,18 +779,18 @@ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, * congested queues, and wake up anyone who was waiting for requests to be * put back. */ -static inline void blk_clear_queue_congested(struct request_queue *q, int rw) +static inline void blk_clear_queue_congested(struct request_queue *q, int sync) { - clear_bdi_congested(&q->backing_dev_info, rw); + clear_bdi_congested(&q->backing_dev_info, sync); } /* * A queue has just entered congestion. Flag that in the queue's VM-visible * state flags and increment the global gounter of congested queues. */ -static inline void blk_set_queue_congested(struct request_queue *q, int rw) +static inline void blk_set_queue_congested(struct request_queue *q, int sync) { - set_bdi_congested(&q->backing_dev_info, rw); + set_bdi_congested(&q->backing_dev_info, sync); } extern void blk_start_queue(struct request_queue *q); diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 493b468a50354..c86edd2442944 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -283,7 +283,6 @@ static wait_queue_head_t congestion_wqh[2] = { __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) }; - void clear_bdi_congested(struct backing_dev_info *bdi, int sync) { enum bdi_state bit; @@ -308,18 +307,18 @@ EXPORT_SYMBOL(set_bdi_congested); /** * congestion_wait - wait for a backing_dev to become uncongested - * @rw: READ or WRITE + * @sync: SYNC or ASYNC IO * @timeout: timeout in jiffies * * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit * write congestion. If no backing_devs are congested then just wait for the * next write to be completed. */ -long congestion_wait(int rw, long timeout) +long congestion_wait(int sync, long timeout) { long ret; DEFINE_WAIT(wait); - wait_queue_head_t *wqh = &congestion_wqh[rw]; + wait_queue_head_t *wqh = &congestion_wqh[sync]; prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); ret = io_schedule_timeout(timeout); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e2fa20dadf408..e717964cb5a0c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1973,7 +1973,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all) if (!progress) { nr_retries--; /* maybe some writeback is necessary */ - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 7687879253b92..81627ebcd313f 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -575,7 +575,7 @@ static void balance_dirty_pages(struct address_space *mapping) if (pages_written >= write_chunk) break; /* We've done our duty */ - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh && @@ -669,7 +669,7 @@ void throttle_vm_writeout(gfp_t gfp_mask) if (global_page_state(NR_UNSTABLE_NFS) + global_page_state(NR_WRITEBACK) <= dirty_thresh) break; - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * The caller might hold locks which can prevent IO completion @@ -715,7 +715,7 @@ static void background_writeout(unsigned long _min_pages) if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) { /* Wrote less than expected */ if (wbc.encountered_congestion || wbc.more_io) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); else break; } @@ -787,7 +787,7 @@ static void wb_kupdate(unsigned long arg) writeback_inodes(&wbc); if (wbc.nr_to_write > 0) { if (wbc.encountered_congestion || wbc.more_io) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); else break; /* All the old data is written */ } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ad7cd1c56b07c..a35eeab2724cc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1666,7 +1666,7 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, preferred_zone, migratetype); if (!page && gfp_mask & __GFP_NOFAIL) - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); } while (!page && (gfp_mask & __GFP_NOFAIL)); return page; @@ -1831,7 +1831,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, pages_reclaimed += did_some_progress; if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) { /* Wait for some write requests to complete then retry */ - congestion_wait(WRITE, HZ/50); + congestion_wait(BLK_RW_ASYNC, HZ/50); goto rebalance; } diff --git a/mm/vmscan.c b/mm/vmscan.c index 54155268dfcae..dea7abd310980 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1104,7 +1104,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, */ if (nr_freed < nr_taken && !current_is_kswapd() && lumpy_reclaim) { - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * The attempt at page out may have made some @@ -1721,7 +1721,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, /* Take a nap, wait for some writeback to complete */ if (sc->nr_scanned && priority < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); } /* top priority shrink_zones still had more to do? don't OOM, then */ if (!sc->all_unreclaimable && scanning_global_lru(sc)) @@ -1960,7 +1960,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) * another pass across the zones. */ if (total_scanned && priority < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ/10); + congestion_wait(BLK_RW_ASYNC, HZ/10); /* * We do this so kswapd doesn't build up large priorities for @@ -2233,7 +2233,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) goto out; if (sc.nr_scanned && prio < DEF_PRIORITY - 2) - congestion_wait(WRITE, HZ / 10); + congestion_wait(BLK_RW_ASYNC, HZ / 10); } } -- GitLab From 76da03467a1a78811777561bbb1fa56175ee4778 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Date: Thu, 9 Jul 2009 09:48:28 +0200 Subject: [PATCH 0917/1002] block: call blk_scsi_ioctl_init() Currently, blk_scsi_ioctl_init() is not called since it lacks an initcall marking. This causes the command table to be unitialized, hence somce commands are block when they should not have been. This fixes a regression introduced by commit 018e0446890661504783f92388ecce7138c1566d Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/scsi_ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index f0e0ce0a607dc..e5b10017a50b1 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -680,3 +680,4 @@ int __init blk_scsi_ioctl_init(void) blk_set_cmd_filter_defaults(&blk_default_cmd_filter); return 0; } +fs_initcall(blk_scsi_ioctl_init); -- GitLab From ecb554a846f8e9d2a58f6d6c118168a63ac065aa Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Date: Thu, 9 Jul 2009 14:46:53 +0200 Subject: [PATCH 0918/1002] block: fix sg SG_DXFER_TO_FROM_DEV regression I overlooked SG_DXFER_TO_FROM_DEV support when I converted sg to use the block layer mapping API (2.6.28). Douglas Gilbert explained SG_DXFER_TO_FROM_DEV: http://www.spinics.net/lists/linux-scsi/msg37135.html = The semantics of SG_DXFER_TO_FROM_DEV were: - copy user space buffer to kernel (LLD) buffer - do SCSI command which is assumed to be of the DATA_IN (data from device) variety. This would overwrite some or all of the kernel buffer - copy kernel (LLD) buffer back to the user space. The idea was to detect short reads by filling the original user space buffer with some marker bytes ("0xec" it would seem in this report). The "resid" value is a better way of detecting short reads but that was only added this century and requires co-operation from the LLD. = This patch changes the block layer mapping API to support this semantics. This simply adds another field to struct rq_map_data and enables __bio_copy_iov() to copy data from user space even with READ requests. It's better to add the flags field and kills null_mapped and the new from_user fields in struct rq_map_data but that approach makes it difficult to send this patch to stable trees because st and osst drivers use struct rq_map_data (they were converted to use the block layer in 2.6.29 and 2.6.30). Well, I should clean up the block layer mapping API. zhou sf reported this regiression and tested this patch: http://www.spinics.net/lists/linux-scsi/msg37128.html http://www.spinics.net/lists/linux-scsi/msg37168.html Reported-by: zhou sf <sxzzsf@gmail.com> Tested-by: zhou sf <sxzzsf@gmail.com> Cc: stable@kernel.org Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- drivers/scsi/sg.c | 4 ++++ fs/bio.c | 22 ++++++++++++---------- include/linux/blkdev.h | 1 + 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4d6f2fe1cfe99..9230402c45afc 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1656,6 +1656,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) md->nr_entries = req_schp->k_use_sg; md->offset = 0; md->null_mapped = hp->dxferp ? 0 : 1; + if (dxfer_dir == SG_DXFER_TO_FROM_DEV) + md->from_user = 1; + else + md->from_user = 0; } if (iov_count) { diff --git a/fs/bio.c b/fs/bio.c index 1486b19fc4315..76738005c8e8a 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -705,14 +705,13 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, } static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, - struct sg_iovec *iov, int iov_count, int uncopy, - int do_free_page) + struct sg_iovec *iov, int iov_count, + int to_user, int from_user, int do_free_page) { int ret = 0, i; struct bio_vec *bvec; int iov_idx = 0; unsigned int iov_off = 0; - int read = bio_data_dir(bio) == READ; __bio_for_each_segment(bvec, bio, i, 0) { char *bv_addr = page_address(bvec->bv_page); @@ -727,13 +726,14 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, iov_addr = iov[iov_idx].iov_base + iov_off; if (!ret) { - if (!read && !uncopy) - ret = copy_from_user(bv_addr, iov_addr, - bytes); - if (read && uncopy) + if (to_user) ret = copy_to_user(iov_addr, bv_addr, bytes); + if (from_user) + ret = copy_from_user(bv_addr, iov_addr, + bytes); + if (ret) ret = -EFAULT; } @@ -770,7 +770,8 @@ int bio_uncopy_user(struct bio *bio) if (!bio_flagged(bio, BIO_NULL_MAPPED)) ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, - bmd->nr_sgvecs, 1, bmd->is_our_pages); + bmd->nr_sgvecs, bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); bio_free_map_data(bmd); bio_put(bio); return ret; @@ -875,8 +876,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q, /* * success */ - if (!write_to_vm && (!map_data || !map_data->null_mapped)) { - ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); + if ((!write_to_vm && (!map_data || !map_data->null_mapped)) || + (map_data && map_data->from_user)) { + ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0); if (ret) goto cleanup; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bb3d399787013..0146e0fecf1aa 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -723,6 +723,7 @@ struct rq_map_data { int nr_entries; unsigned long offset; int null_mapped; + int from_user; }; struct req_iterator { -- GitLab From 32f2e807a3938b24d0831211e6094f9e44b2fc83 Mon Sep 17 00:00:00 2001 From: Vivek Goyal <vgoyal@redhat.com> Date: Thu, 9 Jul 2009 22:13:16 +0200 Subject: [PATCH 0919/1002] cfq-iosched: reset oom_cfqq in cfq_set_request() In case memory is scarce, we now default to oom_cfqq. Once memory is available again, we should allocate a new cfqq and stop using oom_cfqq for a particular io context. Once a new request comes in, check if we are using oom_cfqq, and if yes, try to allocate a new cfqq. Tested the patch by forcing the use of oom_cfqq and upon next request thread realized that it was using oom_cfqq and it allocated a new cfqq. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com> --- block/cfq-iosched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 87276eb83f7f5..fd7080ed79359 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2311,7 +2311,7 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) goto queue_fail; cfqq = cic_to_cfqq(cic, is_sync); - if (!cfqq) { + if (!cfqq || cfqq == &cfqd->oom_cfqq) { cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask); cic_set_cfqq(cic, cfqq, is_sync); } -- GitLab From 2a34f5e6b61c7e8f3b6f25847bcda88511b0ead4 Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Thu, 2 Jul 2009 09:30:50 -0700 Subject: [PATCH 0920/1002] drm/i915: Disable GEM when a broken video BIOS takes up the whole aperture. This is seen on some G41 systems, where the BIOS will consume all but a few KB of the aperture. This should be bad for all operating systems, as it means that the OS can't dynamically manage memory between graphics and the rest of the system, and OSes that did static memory management statically add memory in addition to the BIOS allocation anyway. So, instead of working around it, just fail out verbosely. fd.o bug #21574 Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> --- drivers/gpu/drm/i915/i915_dma.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0e704bb26e99d..8c4783180bf65 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, * some RAM for the framebuffer at early boot. This code figures out * how much was set aside so we can use it for our own purposes. */ -static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, - unsigned long *preallocated_size) +static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, + uint32_t *preallocated_size) { struct pci_dev *bridge_dev; u16 tmp = 0; @@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, return 0; } -static int i915_load_modeset_init(struct drm_device *dev) +static int i915_load_modeset_init(struct drm_device *dev, + unsigned long prealloc_size, + unsigned long agp_size) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long agp_size, prealloc_size; int fb_bar = IS_I9XX(dev) ? 2 : 0; int ret = 0; @@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev) if (IS_I965G(dev) || IS_G33(dev)) dev_priv->cursor_needs_physical = false; - ret = i915_probe_agp(dev, &agp_size, &prealloc_size); - if (ret) - goto out; - /* Basic memrange allocator for stolen space (aka vram) */ drm_mm_init(&dev_priv->vram, 0, prealloc_size); @@ -1136,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) struct drm_i915_private *dev_priv = dev->dev_private; resource_size_t base, size; int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; + uint32_t agp_size, prealloc_size; /* i915 has 4 more counters */ dev->counters += 4; @@ -1184,9 +1182,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) "performance may suffer.\n"); } + ret = i915_probe_agp(dev, &agp_size, &prealloc_size); + if (ret) + goto out_iomapfree; + /* enable GEM by default */ dev_priv->has_gem = 1; + if (prealloc_size > agp_size * 3 / 4) { + DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " + "memory stolen.\n", + prealloc_size / 1024, agp_size / 1024); + DRM_ERROR("Disabling GEM. (try reducing stolen memory or " + "updating the BIOS to fix).\n"); + dev_priv->has_gem = 0; + } + dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ if (IS_G4X(dev) || IS_IGDNG(dev)) { @@ -1231,7 +1242,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = i915_load_modeset_init(dev); + ret = i915_load_modeset_init(dev, prealloc_size, agp_size); if (ret < 0) { DRM_ERROR("failed to init modeset\n"); goto out_rmmap; -- GitLab From 883e860daf5c75a0035c33cb6f8881ee62d6efaf Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Fri, 10 Jul 2009 12:28:30 -0700 Subject: [PATCH 0921/1002] drm/i915: Fix harmless warning from patch merged after i2c rework. Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_crt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 954b8599fc761..d6a1a6e5539a5 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -430,7 +430,7 @@ static int intel_crt_get_modes(struct drm_connector *connector) { int ret; struct intel_output *intel_output = to_intel_output(connector); - struct intel_i2c_chan *ddcbus; + struct i2c_adapter *ddcbus; struct drm_device *dev = connector->dev; -- GitLab From 354ff96772540d2e836194bf14dd9c05c274055c Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Wed, 8 Jul 2009 14:13:12 +0800 Subject: [PATCH 0922/1002] drm/i915: Restore the KMS modeset for every activated CRTC Restore the modeset for every activated CRTC in course of resume. This is realized by calling the function of drm_helper_resume_force_mode. Note: it is meaningful only for the KMS mode. https://bugs.freedesktop.org/show_bug.cgi?id=21719 https://bugs.freedesktop.org/show_bug.cgi?id=21708 https://bugs.freedesktop.org/show_bug.cgi?id=22285 https://bugs.freedesktop.org/show_bug.cgi?id=22263 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aef2a261a8374..fc4b68aa2d056 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -35,6 +35,7 @@ #include "drm_pciids.h" #include <linux/console.h> +#include "drm_crtc_helper.h" static unsigned int i915_modeset = -1; module_param_named(modeset, i915_modeset, int, 0400); @@ -115,6 +116,10 @@ static int i915_resume(struct drm_device *dev) drm_irq_install(dev); } + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + /* Resume the modeset for every activated CRTC */ + drm_helper_resume_force_mode(dev); + } return ret; } -- GitLab From af4fcb574efa90373b02ae0bb8b54d710c32eeb4 Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Wed, 8 Jul 2009 14:13:13 +0800 Subject: [PATCH 0923/1002] drm: Disable the unused connectors explicitly when resuming with KMS. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Acked-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/drm_crtc_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a6f73f1e99d9b..3da9cfa31848c 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1090,6 +1090,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); } + /* disable the unused connectors while restoring the modesetting */ + drm_helper_disable_unused_functions(dev); return 0; } EXPORT_SYMBOL(drm_helper_resume_force_mode); -- GitLab From fccdaba4317604602e5802c3afc4021f2fb8132e Mon Sep 17 00:00:00 2001 From: Zhao Yakui <yakui.zhao@intel.com> Date: Wed, 8 Jul 2009 14:13:14 +0800 Subject: [PATCH 0924/1002] drm/i915: Avoid saving/restore the modesetting registers twice in KMS mode In KMS mode we now use the normal mode-setting paths to set the modes back to the current configuration, so we don't need to also run the more limited non-KMS implementation of modesetting for resume. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_suspend.c | 221 +++++++++++++++------------- 1 file changed, 121 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 8d8e083d14ab2..9e1d16e5c3ead 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -222,23 +222,12 @@ static void i915_restore_vga(struct drm_device *dev) I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); } -int i915_save_state(struct drm_device *dev) +static void i915_save_modeset_reg(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); - - /* Render Standby */ - if (IS_I965G(dev) && IS_MOBILE(dev)) - dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); - - /* Hardware status page */ - dev_priv->saveHWS = I915_READ(HWS_PGA); - - /* Display arbitration control */ - dev_priv->saveDSPARB = I915_READ(DSPARB); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; /* Pipe & plane A info */ dev_priv->savePIPEACONF = I915_READ(PIPEACONF); dev_priv->savePIPEASRC = I915_READ(PIPEASRC); @@ -294,7 +283,122 @@ int i915_save_state(struct drm_device *dev) } i915_save_palette(dev, PIPE_B); dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); + return; +} +static void i915_restore_modeset_reg(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + /* Pipe & plane A info */ + /* Prime the clock */ + if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { + I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & + ~DPLL_VCO_ENABLE); + DRM_UDELAY(150); + } + I915_WRITE(FPA0, dev_priv->saveFPA0); + I915_WRITE(FPA1, dev_priv->saveFPA1); + /* Actually enable it */ + I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); + DRM_UDELAY(150); + if (IS_I965G(dev)) + I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); + DRM_UDELAY(150); + + /* Restore mode */ + I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); + I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); + I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); + I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); + I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); + I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); + I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); + + /* Restore plane info */ + I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); + I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); + I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); + I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); + I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); + if (IS_I965G(dev)) { + I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); + I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); + } + + I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); + + i915_restore_palette(dev, PIPE_A); + /* Enable the plane */ + I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); + I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); + + /* Pipe & plane B info */ + if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { + I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & + ~DPLL_VCO_ENABLE); + DRM_UDELAY(150); + } + I915_WRITE(FPB0, dev_priv->saveFPB0); + I915_WRITE(FPB1, dev_priv->saveFPB1); + /* Actually enable it */ + I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); + DRM_UDELAY(150); + if (IS_I965G(dev)) + I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); + DRM_UDELAY(150); + + /* Restore mode */ + I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); + I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); + I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); + I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); + I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); + I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); + I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); + + /* Restore plane info */ + I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); + I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); + I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); + I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); + I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); + if (IS_I965G(dev)) { + I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); + I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); + } + + I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + + i915_restore_palette(dev, PIPE_B); + /* Enable the plane */ + I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); + I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); + return; +} +int i915_save_state(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + + /* Render Standby */ + if (IS_I965G(dev) && IS_MOBILE(dev)) + dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); + + /* Hardware status page */ + dev_priv->saveHWS = I915_READ(HWS_PGA); + + /* Display arbitration control */ + dev_priv->saveDSPARB = I915_READ(DSPARB); + + /* This is only meaningful in non-KMS mode */ + /* Don't save them in KMS mode */ + i915_save_modeset_reg(dev); /* Cursor state */ dev_priv->saveCURACNTR = I915_READ(CURACNTR); dev_priv->saveCURAPOS = I915_READ(CURAPOS); @@ -430,92 +534,9 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); } - - /* Pipe & plane A info */ - /* Prime the clock */ - if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { - I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & - ~DPLL_VCO_ENABLE); - DRM_UDELAY(150); - } - I915_WRITE(FPA0, dev_priv->saveFPA0); - I915_WRITE(FPA1, dev_priv->saveFPA1); - /* Actually enable it */ - I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); - DRM_UDELAY(150); - if (IS_I965G(dev)) - I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); - DRM_UDELAY(150); - - /* Restore mode */ - I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); - I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); - I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); - I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); - I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); - I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); - I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); - - /* Restore plane info */ - I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); - I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); - I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); - I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); - I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); - if (IS_I965G(dev)) { - I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); - I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); - } - - I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); - - i915_restore_palette(dev, PIPE_A); - /* Enable the plane */ - I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); - I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); - - /* Pipe & plane B info */ - if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { - I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & - ~DPLL_VCO_ENABLE); - DRM_UDELAY(150); - } - I915_WRITE(FPB0, dev_priv->saveFPB0); - I915_WRITE(FPB1, dev_priv->saveFPB1); - /* Actually enable it */ - I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); - DRM_UDELAY(150); - if (IS_I965G(dev)) - I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); - DRM_UDELAY(150); - - /* Restore mode */ - I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); - I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); - I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); - I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); - I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); - I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); - I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); - - /* Restore plane info */ - I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); - I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); - I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); - I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); - I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); - if (IS_I965G(dev)) { - I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); - I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); - } - - I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); - - i915_restore_palette(dev, PIPE_B); - /* Enable the plane */ - I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); - I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); - + /* This is only meaningful in non-KMS mode */ + /* Don't restore them in KMS mode */ + i915_restore_modeset_reg(dev); /* Cursor state */ I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); -- GitLab From f39d1b9792881ce4eb982ec8cc65258bf95674b5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar <mingo@elte.hu> Date: Fri, 10 Jul 2009 21:38:02 +0200 Subject: [PATCH 0925/1002] dma-debug: Fix the overlap() function to be correct and readable Linus noticed how unclean and buggy the overlap() function is: - It uses convoluted (and bug-causing) positive checks for range overlap - instead of using a more natural negative check. - Even the positive checks are buggy: a positive intersection check has four natural cases while we checked only for three, missing the (addr < start && addr2 == end) case for example. - The variables are mis-named, making it non-obvious how the check was done. - It needlessly uses u64 instead of unsigned long. Since these are kernel memory pointers and we explicitly exclude highmem ranges anyway we cannot ever overflow 32 bits, even if we could. (and on 64-bit it doesnt matter anyway) All in one, this function needs a total revamp. I used Linus's suggestions minus the paranoid checks (we cannot overflow really because if we get totally bad DMA ranges passed far more things break in the systems than just DMA debugging). I also fixed a few other small details i noticed. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> --- lib/dma-debug.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index c9187fed0b938..65b0d99b6d0aa 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -856,22 +856,21 @@ static void check_for_stack(struct device *dev, void *addr) "stack [addr=%p]\n", addr); } -static inline bool overlap(void *addr, u64 size, void *start, void *end) +static inline bool overlap(void *addr, unsigned long len, void *start, void *end) { - void *addr2 = (char *)addr + size; + unsigned long a1 = (unsigned long)addr; + unsigned long b1 = a1 + len; + unsigned long a2 = (unsigned long)start; + unsigned long b2 = (unsigned long)end; - return ((addr >= start && addr < end) || - (addr2 >= start && addr2 < end) || - ((addr < start) && (addr2 > end))); + return !(b1 <= a2 || a1 >= b2); } -static void check_for_illegal_area(struct device *dev, void *addr, u64 size) +static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len) { - if (overlap(addr, size, _text, _etext) || - overlap(addr, size, __start_rodata, __end_rodata)) - err_printk(dev, NULL, "DMA-API: device driver maps " - "memory from kernel text or rodata " - "[addr=%p] [size=%llu]\n", addr, size); + if (overlap(addr, len, _text, _etext) || + overlap(addr, len, __start_rodata, __end_rodata)) + err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len); } static void check_sync(struct device *dev, @@ -969,7 +968,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, entry->type = dma_debug_single; if (!PageHighMem(page)) { - void *addr = ((char *)page_address(page)) + offset; + void *addr = page_address(page) + offset; + check_for_stack(dev, addr); check_for_illegal_area(dev, addr, size); } -- GitLab From 901782b21ecb2af4dde1598b3142bf0e80b20853 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 10 Jul 2009 08:18:50 +0100 Subject: [PATCH 0926/1002] drm/i915: Refactor calls to unmap_mapping_range As we call unmap_mapping_range() twice in identical fashion, refactor and attempt to explain why we need to call unmap_mapping_range(). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_gem.c | 36 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 876b65cb7629f..08d8e5d859555 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1252,6 +1252,31 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) return ret; } +/** + * i915_gem_release_mmap - remove physical page mappings + * @obj: obj in question + * + * Preserve the reservation of the mmaping with the DRM core code, but + * relinquish ownership of the pages back to the system. + * + * It is vital that we remove the page mapping if we have mapped a tiled + * object through the GTT and then lose the fence register due to + * resource pressure. Similarly if the object has been moved out of the + * aperture, than pages mapped into userspace must be revoked. Removing the + * mapping will then trigger a page fault on the next user access, allowing + * fixup by i915_gem_fault(). + */ +static void +i915_gem_release_mmap(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + + if (dev->dev_mapping) + unmap_mapping_range(dev->dev_mapping, + obj_priv->mmap_offset, obj->size, 1); +} + static void i915_gem_free_mmap_offset(struct drm_gem_object *obj) { @@ -1861,7 +1886,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; - loff_t offset; int ret = 0; #if WATCH_BUF @@ -1898,9 +1922,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) BUG_ON(obj_priv->active); /* blow away mappings if mapped through GTT */ - offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT; - if (dev->dev_mapping) - unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1); + i915_gem_release_mmap(obj); if (obj_priv->fence_reg != I915_FENCE_REG_NONE) i915_gem_clear_fence_reg(obj); @@ -2222,7 +2244,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { uint32_t seqno = dev_priv->mm.next_gem_seqno; - loff_t offset; if (avail == 0) return -ENOSPC; @@ -2274,10 +2295,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) * Zap this virtual mapping so we can set up a fence again * for this object next time we need it. */ - offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT; - if (dev->dev_mapping) - unmap_mapping_range(dev->dev_mapping, offset, - reg->obj->size, 1); + i915_gem_release_mmap(reg->obj); old_obj_priv->fence_reg = I915_FENCE_REG_NONE; } -- GitLab From d05ca301997c94c2ef3c112b15319d13fa8cddab Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Fri, 10 Jul 2009 13:02:26 -0700 Subject: [PATCH 0927/1002] drm/i915: Zap the GTT mapping when transitioning from untiled to tiled. As of 52dc7d32b88156248167864f77a9026abe27b432, we could leave an old linear GTT mapping in place, so that apps trying to GTT-mapped write in tiled data wouldn't get the fence added, and garbage would get displayed. Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_tiling.c | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9d6889799d01e..d087528758856 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -673,6 +673,7 @@ void i915_gem_free_object(struct drm_gem_object *obj); int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); void i915_gem_object_unpin(struct drm_gem_object *obj); int i915_gem_object_unbind(struct drm_gem_object *obj); +void i915_gem_release_mmap(struct drm_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); uint32_t i915_get_gem_seqno(struct drm_device *dev); int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 08d8e5d859555..5bf420378b6d5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1266,7 +1266,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) * mapping will then trigger a page fault on the next user access, allowing * fixup by i915_gem_fault(). */ -static void +void i915_gem_release_mmap(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index daeae62e1c28b..a2d527b22ec4f 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -521,6 +521,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, goto err; } + /* If we've changed tiling, GTT-mappings of the object + * need to re-fault to ensure that the correct fence register + * setup is in place. + */ + i915_gem_release_mmap(obj); + obj_priv->tiling_mode = args->tiling_mode; obj_priv->stride = args->stride; } -- GitLab From 5019914ca3b7517b2d82db2e92e3f683ac48e535 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang <zhenyu.z.wang@intel.com> Date: Fri, 10 Jul 2009 14:39:59 +0800 Subject: [PATCH 0928/1002] drm/i915: Fix for LVDS VBT change on IGDNG IGDNG mobile chip's LVDS data block removes panel fitting register definition. So this fixes offset for LVDS timing block parsing. Thanks for Michael Fu to catch this. Signed-off-by: Zhenyu Wang <zhenyu.z.wang@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/i915/intel_bios.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index da22863c05c0a..7cc447191028d 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -97,6 +97,7 @@ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { + struct drm_device *dev = dev_priv->dev; struct bdb_lvds_options *lvds_options; struct bdb_lvds_lfp_data *lvds_lfp_data; struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; @@ -132,7 +133,14 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, entry = (struct bdb_lvds_lfp_data_entry *) ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * lvds_options->panel_type)); - dvo_timing = &entry->dvo_timing; + + /* On IGDNG mobile, LVDS data block removes panel fitting registers. + So dec 2 dword from dvo_timing offset */ + if (IS_IGDNG(dev)) + dvo_timing = (struct lvds_dvo_timing *) + ((u8 *)&entry->dvo_timing - 8); + else + dvo_timing = &entry->dvo_timing; panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); -- GitLab From c99e6efe1ba04561e7d93a81f0be07e37427e835 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Fri, 10 Jul 2009 14:57:56 +0200 Subject: [PATCH 0929/1002] sched: INIT_PREEMPT_COUNT Pull the initial preempt_count value into a single definition site. Maintainers for: alpha, ia64 and m68k, please have a look, your arch code is funny. The header magic is a bit odd, but similar to the KERNEL_DS one, CPP waits with expanding these macros until the INIT_THREAD_INFO macro itself is expanded, which is in arch/*/kernel/init_task.c where we've already included sched.h so we're good. Cc: tony.luck@intel.com Cc: rth@twiddle.net Cc: geert@linux-m68k.org Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Matt Mackall <mpm@selenic.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- arch/alpha/include/asm/thread_info.h | 1 + arch/arm/include/asm/thread_info.h | 2 +- arch/avr32/include/asm/thread_info.h | 2 +- arch/blackfin/include/asm/thread_info.h | 2 +- arch/cris/include/asm/thread_info.h | 4 +--- arch/frv/include/asm/thread_info.h | 4 +--- arch/h8300/include/asm/thread_info.h | 2 +- arch/ia64/include/asm/thread_info.h | 2 +- arch/m32r/include/asm/thread_info.h | 4 +--- arch/m68k/include/asm/thread_info_mm.h | 1 + arch/m68k/include/asm/thread_info_no.h | 1 + arch/microblaze/include/asm/thread_info.h | 4 +--- arch/mips/include/asm/thread_info.h | 4 +--- arch/mn10300/include/asm/thread_info.h | 4 +--- arch/parisc/include/asm/thread_info.h | 2 +- arch/powerpc/include/asm/thread_info.h | 4 +--- arch/s390/include/asm/thread_info.h | 2 +- arch/sh/include/asm/thread_info.h | 2 +- arch/sparc/include/asm/thread_info_32.h | 4 +--- arch/sparc/include/asm/thread_info_64.h | 4 +--- arch/um/include/asm/thread_info.h | 2 +- arch/x86/include/asm/thread_info.h | 2 +- arch/xtensa/include/asm/thread_info.h | 4 +--- include/linux/sched.h | 6 ++++++ 24 files changed, 29 insertions(+), 40 deletions(-) diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h index d069526bd7673..60c83abfde702 100644 --- a/arch/alpha/include/asm/thread_info.h +++ b/arch/alpha/include/asm/thread_info.h @@ -37,6 +37,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .addr_limit = KERNEL_DS, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 4f8848260ee2b..73394e50cbca2 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -73,7 +73,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ diff --git a/arch/avr32/include/asm/thread_info.h b/arch/avr32/include/asm/thread_info.h index 4442f8d2d4239..fc42de5ca209a 100644 --- a/arch/avr32/include/asm/thread_info.h +++ b/arch/avr32/include/asm/thread_info.h @@ -40,7 +40,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall \ } \ diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h index 2920087516f2a..2bbfdd950afc4 100644 --- a/arch/blackfin/include/asm/thread_info.h +++ b/arch/blackfin/include/asm/thread_info.h @@ -77,7 +77,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h index bc5b2935ca53a..c3aade36c3304 100644 --- a/arch/cris/include/asm/thread_info.h +++ b/arch/cris/include/asm/thread_info.h @@ -50,8 +50,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ #define INIT_THREAD_INFO(tsk) \ @@ -60,7 +58,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h index e8a5ed7be0212..e608e056bb530 100644 --- a/arch/frv/include/asm/thread_info.h +++ b/arch/frv/include/asm/thread_info.h @@ -56,8 +56,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -67,7 +65,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h index 700014d2155fd..8bbc8b0ee45db 100644 --- a/arch/h8300/include/asm/thread_info.h +++ b/arch/h8300/include/asm/thread_info.h @@ -36,7 +36,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h index ae6922626bf49..8ce2e388e37c5 100644 --- a/arch/ia64/include/asm/thread_info.h +++ b/arch/ia64/include/asm/thread_info.h @@ -48,7 +48,7 @@ struct thread_info { .flags = 0, \ .cpu = 0, \ .addr_limit = KERNEL_DS, \ - .preempt_count = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/m32r/include/asm/thread_info.h b/arch/m32r/include/asm/thread_info.h index 8589d462df27e..07bb5bd00e2a0 100644 --- a/arch/m32r/include/asm/thread_info.h +++ b/arch/m32r/include/asm/thread_info.h @@ -57,8 +57,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -68,7 +66,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/m68k/include/asm/thread_info_mm.h b/arch/m68k/include/asm/thread_info_mm.h index af0fda46e94bc..6ea5c33b3c564 100644 --- a/arch/m68k/include/asm/thread_info_mm.h +++ b/arch/m68k/include/asm/thread_info_mm.h @@ -19,6 +19,7 @@ struct thread_info { { \ .task = &tsk, \ .exec_domain = &default_exec_domain, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/m68k/include/asm/thread_info_no.h b/arch/m68k/include/asm/thread_info_no.h index 82529f424ea3d..c2bde5e24b0b9 100644 --- a/arch/m68k/include/asm/thread_info_no.h +++ b/arch/m68k/include/asm/thread_info_no.h @@ -49,6 +49,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h index 7fac44498445f..6e92885d381a8 100644 --- a/arch/microblaze/include/asm/thread_info.h +++ b/arch/microblaze/include/asm/thread_info.h @@ -75,8 +75,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -84,7 +82,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 143a48136a4b0..f9df720d2e40e 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -39,8 +39,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -48,7 +46,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = _TIF_FIXADE, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h index 78a3881f3c125..58d64f8b2cc3d 100644 --- a/arch/mn10300/include/asm/thread_info.h +++ b/arch/mn10300/include/asm/thread_info.h @@ -65,8 +65,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -76,7 +74,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 0407959da489d..4ce0edfbe9694 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h @@ -23,7 +23,7 @@ struct thread_info { .flags = 0, \ .cpu = 0, \ .addr_limit = KERNEL_DS, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall \ } \ diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 9aba5a38a7c4f..c8b3292556788 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -46,15 +46,13 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ .task = &tsk, \ .exec_domain = &default_exec_domain, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 925bcc6490354..ba1cab9fc1f92 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -61,7 +61,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index f09ac48062940..d570ac2e5cb99 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h @@ -51,7 +51,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index 0f7b0e5fb1c79..844d73a0340cd 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -54,8 +54,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #define INIT_THREAD_INFO(tsk) \ { \ @@ -64,7 +62,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 65865726b2831..1b45a7bbe4075 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -125,8 +125,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -135,7 +133,7 @@ struct thread_info { .task = &tsk, \ .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ .exec_domain = &default_exec_domain, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 62274ab9471fe..fd911f855367a 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -32,7 +32,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index b0783520988b8..fad7d40b75f89 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -49,7 +49,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index 0f4fe1faf9ba4..13165641cc515 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h @@ -80,8 +80,6 @@ struct thread_info { /* * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. */ #ifndef __ASSEMBLY__ @@ -92,7 +90,7 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ + .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ .restart_block = { \ .fn = do_no_restart_syscall, \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 0085d758d6453..2a99f1c15cf80 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -498,6 +498,12 @@ struct task_cputime { .sum_exec_runtime = 0, \ } +/* + * Disable preemption until the scheduler is running. + * Reset by start_kernel()->sched_init()->init_idle(). + */ +#define INIT_PREEMPT_COUNT (1) + /** * struct thread_group_cputimer - thread group interval timer counts * @cputime: thread group interval timers. -- GitLab From d86ee4809d0329d4aa0d0f2c76c2295a16862799 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra <a.p.zijlstra@chello.nl> Date: Fri, 10 Jul 2009 14:57:57 +0200 Subject: [PATCH 0930/1002] sched: optimize cond_resched() Optimize cond_resched() by removing one conditional. Currently cond_resched() checks system_state == SYSTEM_RUNNING in order to avoid scheduling before the scheduler is running. We can however, as per suggestion of Matt, use PREEMPT_ACTIVE to accomplish that very same. Suggested-by: Matt Mackall <mpm@selenic.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Matt Mackall <mpm@selenic.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/sched.h | 5 ++++- kernel/sched.c | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2a99f1c15cf80..16a982e389fb2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -501,8 +501,11 @@ struct task_cputime { /* * Disable preemption until the scheduler is running. * Reset by start_kernel()->sched_init()->init_idle(). + * + * We include PREEMPT_ACTIVE to avoid cond_resched() from working + * before the scheduler is active -- see should_resched(). */ -#define INIT_PREEMPT_COUNT (1) +#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE) /** * struct thread_group_cputimer - thread group interval timer counts diff --git a/kernel/sched.c b/kernel/sched.c index 7c9098d186e6f..01f55ada3598a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6541,6 +6541,11 @@ SYSCALL_DEFINE0(sched_yield) return 0; } +static inline int should_resched(void) +{ + return need_resched() && !(preempt_count() & PREEMPT_ACTIVE); +} + static void __cond_resched(void) { #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP @@ -6560,8 +6565,7 @@ static void __cond_resched(void) int __sched _cond_resched(void) { - if (need_resched() && !(preempt_count() & PREEMPT_ACTIVE) && - system_state == SYSTEM_RUNNING) { + if (should_resched()) { __cond_resched(); return 1; } @@ -6579,12 +6583,12 @@ EXPORT_SYMBOL(_cond_resched); */ int cond_resched_lock(spinlock_t *lock) { - int resched = need_resched() && system_state == SYSTEM_RUNNING; + int resched = should_resched(); int ret = 0; if (spin_needbreak(lock) || resched) { spin_unlock(lock); - if (resched && need_resched()) + if (resched) __cond_resched(); else cpu_relax(); @@ -6599,7 +6603,7 @@ int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched() && system_state == SYSTEM_RUNNING) { + if (should_resched()) { local_bh_enable(); __cond_resched(); local_bh_disable(); -- GitLab From 097041e576ee3a50d92dd643ee8ca65bf6a62e21 Mon Sep 17 00:00:00 2001 From: Larry Finger <Larry.Finger@lwfinger.net> Date: Fri, 10 Jul 2009 20:06:42 -0500 Subject: [PATCH 0931/1002] fuse: Fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building v2.6.31-rc2-344-g69ca06c, the following build errors are found due to missing includes: CC [M] fs/fuse/dev.o fs/fuse/dev.c: In function ‘request_end’: fs/fuse/dev.c:289: error: ‘BLK_RW_SYNC’ undeclared (first use in this function) ... fs/nfs/write.c: In function ‘nfs_set_page_writeback’: fs/nfs/write.c:207: error: ‘BLK_RW_ASYNC’ undeclared (first use in this function) Signed-off-by: Larry Finger@lwfinger.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/fuse/dev.c | 1 + fs/nfs/write.c | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 6484eb75acd6f..cbceacbc0bf91 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -16,6 +16,7 @@ #include <linux/pagemap.h> #include <linux/file.h> #include <linux/slab.h> +#include <linux/blkdev.h> MODULE_ALIAS_MISCDEV(FUSE_MINOR); diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0a0a2ff767c31..35d81316163fc 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -19,6 +19,7 @@ #include <linux/nfs_mount.h> #include <linux/nfs_page.h> #include <linux/backing-dev.h> +#include <linux/blkdev.h> #include <asm/uaccess.h> -- GitLab From 3697cd9aa80125f7717c3c7e7253cfa49a39a388 Mon Sep 17 00:00:00 2001 From: Amerigo Wang <amwang@redhat.com> Date: Fri, 10 Jul 2009 15:02:41 -0700 Subject: [PATCH 0932/1002] Doc: update Documentation/exception.txt Update Documentation/exception.txt. Remove trailing whitespaces in it. Signed-off-by: WANG Cong <amwang@redhat.com> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/exception.txt | 202 ++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/Documentation/exception.txt b/Documentation/exception.txt index 2d5aded642473..32901aa36f0a9 100644 --- a/Documentation/exception.txt +++ b/Documentation/exception.txt @@ -1,123 +1,123 @@ - Kernel level exception handling in Linux 2.1.8 + Kernel level exception handling in Linux Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com> -When a process runs in kernel mode, it often has to access user -mode memory whose address has been passed by an untrusted program. +When a process runs in kernel mode, it often has to access user +mode memory whose address has been passed by an untrusted program. To protect itself the kernel has to verify this address. -In older versions of Linux this was done with the -int verify_area(int type, const void * addr, unsigned long size) +In older versions of Linux this was done with the +int verify_area(int type, const void * addr, unsigned long size) function (which has since been replaced by access_ok()). -This function verified that the memory area starting at address +This function verified that the memory area starting at address 'addr' and of size 'size' was accessible for the operation specified -in type (read or write). To do this, verify_read had to look up the -virtual memory area (vma) that contained the address addr. In the -normal case (correctly working program), this test was successful. +in type (read or write). To do this, verify_read had to look up the +virtual memory area (vma) that contained the address addr. In the +normal case (correctly working program), this test was successful. It only failed for a few buggy programs. In some kernel profiling tests, this normally unneeded verification used up a considerable amount of time. -To overcome this situation, Linus decided to let the virtual memory +To overcome this situation, Linus decided to let the virtual memory hardware present in every Linux-capable CPU handle this test. How does this work? -Whenever the kernel tries to access an address that is currently not -accessible, the CPU generates a page fault exception and calls the -page fault handler +Whenever the kernel tries to access an address that is currently not +accessible, the CPU generates a page fault exception and calls the +page fault handler void do_page_fault(struct pt_regs *regs, unsigned long error_code) -in arch/i386/mm/fault.c. The parameters on the stack are set up by -the low level assembly glue in arch/i386/kernel/entry.S. The parameter -regs is a pointer to the saved registers on the stack, error_code +in arch/x86/mm/fault.c. The parameters on the stack are set up by +the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter +regs is a pointer to the saved registers on the stack, error_code contains a reason code for the exception. -do_page_fault first obtains the unaccessible address from the CPU -control register CR2. If the address is within the virtual address -space of the process, the fault probably occurred, because the page -was not swapped in, write protected or something similar. However, -we are interested in the other case: the address is not valid, there -is no vma that contains this address. In this case, the kernel jumps -to the bad_area label. - -There it uses the address of the instruction that caused the exception -(i.e. regs->eip) to find an address where the execution can continue -(fixup). If this search is successful, the fault handler modifies the -return address (again regs->eip) and returns. The execution will +do_page_fault first obtains the unaccessible address from the CPU +control register CR2. If the address is within the virtual address +space of the process, the fault probably occurred, because the page +was not swapped in, write protected or something similar. However, +we are interested in the other case: the address is not valid, there +is no vma that contains this address. In this case, the kernel jumps +to the bad_area label. + +There it uses the address of the instruction that caused the exception +(i.e. regs->eip) to find an address where the execution can continue +(fixup). If this search is successful, the fault handler modifies the +return address (again regs->eip) and returns. The execution will continue at the address in fixup. Where does fixup point to? -Since we jump to the contents of fixup, fixup obviously points -to executable code. This code is hidden inside the user access macros. -I have picked the get_user macro defined in include/asm/uaccess.h as an -example. The definition is somewhat hard to follow, so let's peek at +Since we jump to the contents of fixup, fixup obviously points +to executable code. This code is hidden inside the user access macros. +I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h +as an example. The definition is somewhat hard to follow, so let's peek at the code generated by the preprocessor and the compiler. I selected -the get_user call in drivers/char/console.c for a detailed examination. +the get_user call in drivers/char/sysrq.c for a detailed examination. -The original code in console.c line 1405: +The original code in sysrq.c line 587: get_user(c, buf); The preprocessor output (edited to become somewhat readable): ( - { - long __gu_err = - 14 , __gu_val = 0; - const __typeof__(*( ( buf ) )) *__gu_addr = ((buf)); - if (((((0 + current_set[0])->tss.segment) == 0x18 ) || - (((sizeof(*(buf))) <= 0xC0000000UL) && - ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf))))))) + { + long __gu_err = - 14 , __gu_val = 0; + const __typeof__(*( ( buf ) )) *__gu_addr = ((buf)); + if (((((0 + current_set[0])->tss.segment) == 0x18 ) || + (((sizeof(*(buf))) <= 0xC0000000UL) && + ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf))))))) do { - __gu_err = 0; - switch ((sizeof(*(buf)))) { - case 1: - __asm__ __volatile__( - "1: mov" "b" " %2,%" "b" "1\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: movl %3,%0\n" - " xor" "b" " %" "b" "1,%" "b" "1\n" - " jmp 2b\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,3b\n" + __gu_err = 0; + switch ((sizeof(*(buf)))) { + case 1: + __asm__ __volatile__( + "1: mov" "b" " %2,%" "b" "1\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %3,%0\n" + " xor" "b" " %" "b" "1,%" "b" "1\n" + " jmp 2b\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,3b\n" ".text" : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *) - ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ; - break; - case 2: + ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ; + break; + case 2: __asm__ __volatile__( - "1: mov" "w" " %2,%" "w" "1\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: movl %3,%0\n" - " xor" "w" " %" "w" "1,%" "w" "1\n" - " jmp 2b\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,3b\n" + "1: mov" "w" " %2,%" "w" "1\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %3,%0\n" + " xor" "w" " %" "w" "1,%" "w" "1\n" + " jmp 2b\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,3b\n" ".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *) - ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )); - break; - case 4: - __asm__ __volatile__( - "1: mov" "l" " %2,%" "" "1\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: movl %3,%0\n" - " xor" "l" " %" "" "1,%" "" "1\n" - " jmp 2b\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" " .long 1b,3b\n" + ( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )); + break; + case 4: + __asm__ __volatile__( + "1: mov" "l" " %2,%" "" "1\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %3,%0\n" + " xor" "l" " %" "" "1,%" "" "1\n" + " jmp 2b\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" " .long 1b,3b\n" ".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *) - ( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err)); - break; - default: - (__gu_val) = __get_user_bad(); - } - } while (0) ; - ((c)) = (__typeof__(*((buf))))__gu_val; + ( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err)); + break; + default: + (__gu_val) = __get_user_bad(); + } + } while (0) ; + ((c)) = (__typeof__(*((buf))))__gu_val; __gu_err; } ); @@ -127,12 +127,12 @@ see what code gcc generates: > xorl %edx,%edx > movl current_set,%eax - > cmpl $24,788(%eax) - > je .L1424 + > cmpl $24,788(%eax) + > je .L1424 > cmpl $-1073741825,64(%esp) - > ja .L1423 + > ja .L1423 > .L1424: - > movl %edx,%eax + > movl %edx,%eax > movl 64(%esp),%ebx > #APP > 1: movb (%ebx),%dl /* this is the actual user access */ @@ -149,17 +149,17 @@ see what code gcc generates: > .L1423: > movzbl %dl,%esi -The optimizer does a good job and gives us something we can actually -understand. Can we? The actual user access is quite obvious. Thanks -to the unified address space we can just access the address in user +The optimizer does a good job and gives us something we can actually +understand. Can we? The actual user access is quite obvious. Thanks +to the unified address space we can just access the address in user memory. But what does the .section stuff do????? To understand this we have to look at the final kernel: > objdump --section-headers vmlinux - > + > > vmlinux: file format elf32-i386 - > + > > Sections: > Idx Name Size VMA LMA File off Algn > 0 .text 00098f40 c0100000 c0100000 00001000 2**4 @@ -198,18 +198,18 @@ final kernel executable: The whole user memory access is reduced to 10 x86 machine instructions. The instructions bracketed in the .section directives are no longer -in the normal execution path. They are located in a different section +in the normal execution path. They are located in a different section of the executable file: > objdump --disassemble --section=.fixup vmlinux - > + > > c0199ff5 <.fixup+10b5> movl $0xfffffff2,%eax > c0199ffa <.fixup+10ba> xorb %dl,%dl > c0199ffc <.fixup+10bc> jmp c017e7a7 <do_con_write+e3> And finally: > objdump --full-contents --section=__ex_table vmlinux - > + > > c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0 ................ > c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0 ................ > c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0 ................ @@ -235,8 +235,8 @@ sections in the ELF object file. So the instructions ended up in the .fixup section of the object file and the addresses .long 1b,3b ended up in the __ex_table section of the object file. 1b and 3b -are local labels. The local label 1b (1b stands for next label 1 -backward) is the address of the instruction that might fault, i.e. +are local labels. The local label 1b (1b stands for next label 1 +backward) is the address of the instruction that might fault, i.e. in our case the address of the label 1 is c017e7a5: the original assembly code: > 1: movb (%ebx),%dl and linked in vmlinux : > c017e7a5 <do_con_write+e1> movb (%ebx),%dl @@ -254,7 +254,7 @@ The assembly code becomes the value pair > c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5 ................ ^this is ^this is - 1b 3b + 1b 3b c017e7a5,c0199ff5 in the exception table of the kernel. So, what actually happens if a fault from kernel mode with no suitable @@ -266,9 +266,9 @@ vma occurs? 3.) CPU calls do_page_fault 4.) do page fault calls search_exception_table (regs->eip == c017e7a5); 5.) search_exception_table looks up the address c017e7a5 in the - exception table (i.e. the contents of the ELF section __ex_table) + exception table (i.e. the contents of the ELF section __ex_table) and returns the address of the associated fault handle code c0199ff5. -6.) do_page_fault modifies its own return address to point to the fault +6.) do_page_fault modifies its own return address to point to the fault handle code and returns. 7.) execution continues in the fault handling code. 8.) 8a) EAX becomes -EFAULT (== -14) -- GitLab From c368b4921bc6e309aba2fbee0efcbbc965008d9f Mon Sep 17 00:00:00 2001 From: Amerigo Wang <amwang@redhat.com> Date: Fri, 10 Jul 2009 15:02:44 -0700 Subject: [PATCH 0933/1002] Doc: move Documentation/exception.txt into x86 subdir exception.txt only explains the code on x86, so it's better to move it into Documentation/x86 directory. And also rename it to exception-tables.txt which looks much more reasonable. This patch is on top of the previous one. Signed-off-by: WANG Cong <amwang@redhat.com> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- Documentation/x86/00-INDEX | 2 ++ Documentation/{exception.txt => x86/exception-tables.txt} | 0 2 files changed, 2 insertions(+) rename Documentation/{exception.txt => x86/exception-tables.txt} (100%) diff --git a/Documentation/x86/00-INDEX b/Documentation/x86/00-INDEX index dbe3377754af5..f37b46d348614 100644 --- a/Documentation/x86/00-INDEX +++ b/Documentation/x86/00-INDEX @@ -2,3 +2,5 @@ - this file mtrr.txt - how to use x86 Memory Type Range Registers to increase performance +exception-tables.txt + - why and how Linux kernel uses exception tables on x86 diff --git a/Documentation/exception.txt b/Documentation/x86/exception-tables.txt similarity index 100% rename from Documentation/exception.txt rename to Documentation/x86/exception-tables.txt -- GitLab From 4cd1de0afaaa45309f34d7282ea4c07d9b56a3ff Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Thu, 9 Jul 2009 13:35:52 +0100 Subject: [PATCH 0934/1002] tty: Sort out the USB sysrq changes that wrecked performance We can't go around calling all sorts of magic per character functions at full rate 3G data speed. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/serial/generic.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 932d6241b787d..3d8dc5671beac 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -424,10 +424,17 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) if (!tty) goto done; - /* Push data to tty */ - for (i = 0; i < urb->actual_length; i++, ch++) { - if (!usb_serial_handle_sysrq_char(port, *ch)) - tty_insert_flip_char(tty, *ch, TTY_NORMAL); + /* The per character mucking around with sysrq path it too slow for + stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases + where the USB serial is not a console anyway */ + if (!port->console || !port->sysrq) + tty_insert_flip_string(tty, ch, urb->actual_length); + else { + /* Push data to tty */ + for (i = 0; i < urb->actual_length; i++, ch++) { + if (!usb_serial_handle_sysrq_char(port, *ch)) + tty_insert_flip_char(tty, *ch, TTY_NORMAL); + } } tty_flip_buffer_push(tty); tty_kref_put(tty); -- GitLab From 24a15a62dcb1968bf4ffdae55c88fa934d971180 Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Thu, 9 Jul 2009 13:36:22 +0100 Subject: [PATCH 0935/1002] tty: Fix USB kref leak The sysrq code acquired a kref leak. Fix it by passing the tty separately from the caller (thus effectively using the callers kref which all the callers hold anyway) Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/generic.c | 7 ++++--- drivers/usb/serial/pl2303.c | 2 +- include/linux/usb/serial.h | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3dc3768ca71ca..5f08702f672f6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2121,7 +2121,7 @@ static void ftdi_process_read(struct work_struct *work) /* Note that the error flag is duplicated for every character received since we don't know which character it applied to */ - if (!usb_serial_handle_sysrq_char(port, + if (!usb_serial_handle_sysrq_char(tty, port, data[packet_offset + i])) tty_insert_flip_char(tty, data[packet_offset + i], diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 3d8dc5671beac..ce57f6a32bdfb 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -432,7 +432,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) else { /* Push data to tty */ for (i = 0; i < urb->actual_length; i++, ch++) { - if (!usb_serial_handle_sysrq_char(port, *ch)) + if (!usb_serial_handle_sysrq_char(tty, port, *ch)) tty_insert_flip_char(tty, *ch, TTY_NORMAL); } } @@ -534,11 +534,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) } } -int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) +int usb_serial_handle_sysrq_char(struct tty_struct *tty, + struct usb_serial_port *port, unsigned int ch) { if (port->sysrq && port->console) { if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch, tty_port_tty_get(&port->port)); + handle_sysrq(ch, tty); port->sysrq = 0; return 1; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ec6c132a25b56..8835802067f7a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -1038,7 +1038,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) if (line_status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); for (i = 0; i < urb->actual_length; ++i) - if (!usb_serial_handle_sysrq_char(port, data[i])) + if (!usb_serial_handle_sysrq_char(tty, port, data[i])) tty_insert_flip_char(tty, data[i], tty_flag); tty_flip_buffer_push(tty); } diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 44801d26a37a7..0ec50ba62139e 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -317,7 +317,8 @@ extern int usb_serial_generic_register(int debug); extern void usb_serial_generic_deregister(void); extern void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags); -extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port, +extern int usb_serial_handle_sysrq_char(struct tty_struct *tty, + struct usb_serial_port *port, unsigned int ch); extern int usb_serial_handle_break(struct usb_serial_port *port); -- GitLab From d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6 Mon Sep 17 00:00:00 2001 From: Alan Cox <alan@linux.intel.com> Date: Thu, 9 Jul 2009 13:36:58 +0100 Subject: [PATCH 0936/1002] tty: Fix the PL2303 private methods for sysrq PL2303 has private data shovelling methods that also have no fast path. Fix them to work the same way as the default handler. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- drivers/usb/serial/pl2303.c | 58 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8835802067f7a..efaf59c4f5d01 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -971,18 +971,46 @@ static void pl2303_read_int_callback(struct urb *urb) __func__, retval); } +static void pl2303_push_data(struct tty_struct *tty, + struct usb_serial_port *port, struct urb *urb, + u8 line_status) +{ + unsigned char *data = urb->transfer_buffer; + /* get tty_flag from status */ + char tty_flag = TTY_NORMAL; + /* break takes precedence over parity, */ + /* which takes precedence over framing errors */ + if (line_status & UART_BREAK_ERROR) + tty_flag = TTY_BREAK; + else if (line_status & UART_PARITY_ERROR) + tty_flag = TTY_PARITY; + else if (line_status & UART_FRAME_ERROR) + tty_flag = TTY_FRAME; + dbg("%s - tty_flag = %d", __func__, tty_flag); + + tty_buffer_request_room(tty, urb->actual_length + 1); + /* overrun is special, not associated with a char */ + if (line_status & UART_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + if (port->console && port->sysrq) { + int i; + for (i = 0; i < urb->actual_length; ++i) + if (!usb_serial_handle_sysrq_char(tty, port, data[i])) + tty_insert_flip_char(tty, data[i], tty_flag); + } else + tty_insert_flip_string(tty, data, urb->actual_length); + tty_flip_buffer_push(tty); +} + static void pl2303_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct pl2303_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; unsigned long flags; - int i; int result; int status = urb->status; u8 line_status; - char tty_flag; dbg("%s - port %d", __func__, port->number); @@ -1010,10 +1038,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) } usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); - - /* get tty_flag from status */ - tty_flag = TTY_NORMAL; + urb->actual_length, urb->transfer_buffer); spin_lock_irqsave(&priv->lock, flags); line_status = priv->line_status; @@ -1021,26 +1046,9 @@ static void pl2303_read_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); wake_up_interruptible(&priv->delta_msr_wait); - /* break takes precedence over parity, */ - /* which takes precedence over framing errors */ - if (line_status & UART_BREAK_ERROR) - tty_flag = TTY_BREAK; - else if (line_status & UART_PARITY_ERROR) - tty_flag = TTY_PARITY; - else if (line_status & UART_FRAME_ERROR) - tty_flag = TTY_FRAME; - dbg("%s - tty_flag = %d", __func__, tty_flag); - tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length + 1); - /* overrun is special, not associated with a char */ - if (line_status & UART_OVERRUN_ERROR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - for (i = 0; i < urb->actual_length; ++i) - if (!usb_serial_handle_sysrq_char(tty, port, data[i])) - tty_insert_flip_char(tty, data[i], tty_flag); - tty_flip_buffer_push(tty); + pl2303_push_data(tty, port, urb, line_status); } tty_kref_put(tty); /* Schedule the next read _if_ we are still open */ -- GitLab From 8711c67bee675b4f7a378c71ad5a59c981ec3df0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Date: Fri, 10 Jul 2009 12:34:27 +0200 Subject: [PATCH 0937/1002] isofs: fix Joliet regression commit 5404ac8e4418ab3d254950ee4f9bcafc1da20b4a ("isofs: cleanup mount option processing") missed conversion of joliet option flag resulting in non-working Joliet support. CC: walt <w41ter@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/isofs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 58a7963e168ae..85f96bc651c72 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -142,6 +142,7 @@ static const struct dentry_operations isofs_dentry_ops[] = { struct iso9660_options{ unsigned int rock:1; + unsigned int joliet:1; unsigned int cruft:1; unsigned int hide:1; unsigned int showassoc:1; @@ -151,7 +152,6 @@ struct iso9660_options{ unsigned int gid_set:1; unsigned int utf8:1; unsigned char map; - char joliet; unsigned char check; unsigned int blocksize; mode_t fmode; @@ -632,7 +632,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) { sec = (struct iso_supplementary_descriptor *)vdp; if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { - if (opt.joliet == 'y') { + if (opt.joliet) { if (sec->escape[2] == 0x40) joliet_level = 1; else if (sec->escape[2] == 0x43) -- GitLab From 0724915a69433716704bc5de6f729d3751981be6 Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Sat, 11 Jul 2009 09:33:21 +0800 Subject: [PATCH 0938/1002] [ARM] remove duplicated #include Remove duplicated #include('s) in drivers/spi/amba-pl022.c Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- drivers/spi/amba-pl022.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index da76797ce8b9d..c0f950a7cbec0 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -38,14 +38,12 @@ #include <linux/interrupt.h> #include <linux/spi/spi.h> #include <linux/workqueue.h> -#include <linux/errno.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> #include <linux/io.h> -#include <linux/delay.h> /* * This macro is used to define some register default values. -- GitLab From ee0049d49ad2556222a7b3127be2dae11982f7b3 Mon Sep 17 00:00:00 2001 From: Huang Weiyi <weiyi.huang@gmail.com> Date: Sat, 11 Jul 2009 09:31:58 +0800 Subject: [PATCH 0939/1002] [ARM] remove duplicated #include Remove duplicated #include('s) in arch/arm/mach-mx3/devices.c arch/arm/mach-omap1/mcbsp.c arch/arm/mach-omap2/mcbsp.c arch/arm/plat-stmp3xxx/pinmux.c Signed-off-by: Huang Weiyi <weiyi.huang@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-mx3/devices.c | 1 - arch/arm/mach-omap1/mcbsp.c | 1 - arch/arm/mach-omap2/mcbsp.c | 1 - arch/arm/plat-stmp3xxx/pinmux.c | 1 - 4 files changed, 4 deletions(-) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index d927eddcad460..9e87e08fb121f 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -22,7 +22,6 @@ #include <linux/platform_device.h> #include <linux/serial.h> #include <linux/gpio.h> -#include <linux/dma-mapping.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/common.h> diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index a2d7814896bea..505d98cfe508c 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -19,7 +19,6 @@ #include <mach/irqs.h> #include <mach/dma.h> -#include <mach/irqs.h> #include <mach/mux.h> #include <mach/cpu.h> #include <mach/mcbsp.h> diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index a5c0f0435cd67..99b6e15463118 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -19,7 +19,6 @@ #include <mach/irqs.h> #include <mach/dma.h> -#include <mach/irqs.h> #include <mach/mux.h> #include <mach/cpu.h> #include <mach/mcbsp.h> diff --git a/arch/arm/plat-stmp3xxx/pinmux.c b/arch/arm/plat-stmp3xxx/pinmux.c index d41200382208c..6d6b1a468eda7 100644 --- a/arch/arm/plat-stmp3xxx/pinmux.c +++ b/arch/arm/plat-stmp3xxx/pinmux.c @@ -22,7 +22,6 @@ #include <linux/sysdev.h> #include <linux/string.h> #include <linux/bitops.h> -#include <linux/sysdev.h> #include <linux/irq.h> #include <mach/hardware.h> -- GitLab From f7a55fa6ecef8be6d15bd79a803e44a3187ce9d6 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sat, 11 Jul 2009 16:51:40 +0100 Subject: [PATCH 0940/1002] [ARM] remove L_PTE_BUFFERABLE and L_PTE_CACHEABLE These old symbols are meaningless now that we have memory type support implemented. The entire memory type field needs to be modified rather than just a few bits twiddled. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/pgtable.h | 2 -- arch/arm/mm/proc-macros.S | 6 ------ 2 files changed, 8 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index c433c6c73112a..d575666d5c469 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -164,8 +164,6 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define L_PTE_PRESENT (1 << 0) #define L_PTE_FILE (1 << 1) /* only when !PRESENT */ #define L_PTE_YOUNG (1 << 1) -#define L_PTE_BUFFERABLE (1 << 2) /* obsolete, matches PTE */ -#define L_PTE_CACHEABLE (1 << 3) /* obsolete, matches PTE */ #define L_PTE_DIRTY (1 << 6) #define L_PTE_WRITE (1 << 7) #define L_PTE_USER (1 << 8) diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 54b1f721dec88..a0b3f36f31788 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -80,12 +80,6 @@ #if L_PTE_SHARED != PTE_EXT_SHARED #error PTE shared bit mismatch #endif -#if L_PTE_BUFFERABLE != PTE_BUFFERABLE -#error PTE bufferable bit mismatch -#endif -#if L_PTE_CACHEABLE != PTE_CACHEABLE -#error PTE cacheable bit mismatch -#endif #if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\ L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED #error Invalid Linux PTE bit settings -- GitLab From 6a00cded91532f3d58e07729ba56269339281d8e Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sat, 11 Jul 2009 16:57:20 +0100 Subject: [PATCH 0941/1002] [ARM] pgtable: rearrange file PTE bit allocation For future compatibility, we need to ensure that swap and file Linux PTEs conform with the hardware PTEs "fault" encoding. Swap PTEs already fit in with this, but file PTEs do not. Shift them by one bit to ensure that they conform, using bit 2 to distinguish between swap and file PTEs. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/pgtable.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index d575666d5c469..9655bce3d3452 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -162,8 +162,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val); * entries are stored 1024 bytes below. */ #define L_PTE_PRESENT (1 << 0) -#define L_PTE_FILE (1 << 1) /* only when !PRESENT */ #define L_PTE_YOUNG (1 << 1) +#define L_PTE_FILE (1 << 2) /* only when !PRESENT */ #define L_PTE_DIRTY (1 << 6) #define L_PTE_WRITE (1 << 7) #define L_PTE_USER (1 << 8) @@ -379,13 +379,13 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <--------------- offset --------------------> <--- type --> 0 0 + * <--------------- offset --------------------> <- type --> 0 0 0 * - * This gives us up to 127 swap files and 32GB per swap file. Note that + * This gives us up to 63 swap files and 32GB per swap file. Note that * the offset field is always non-zero. */ -#define __SWP_TYPE_SHIFT 2 -#define __SWP_TYPE_BITS 7 +#define __SWP_TYPE_SHIFT 3 +#define __SWP_TYPE_BITS 6 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) @@ -409,13 +409,13 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <------------------------ offset -------------------------> 1 0 + * <----------------------- offset ------------------------> 1 0 0 */ #define pte_file(pte) (pte_val(pte) & L_PTE_FILE) -#define pte_to_pgoff(x) (pte_val(x) >> 2) -#define pgoff_to_pte(x) __pte(((x) << 2) | L_PTE_FILE) +#define pte_to_pgoff(x) (pte_val(x) >> 3) +#define pgoff_to_pte(x) __pte(((x) << 3) | L_PTE_FILE) -#define PTE_FILE_MAX_BITS 30 +#define PTE_FILE_MAX_BITS 29 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ -- GitLab From 5396730b3caad500ceba84c9391143cafb5938a8 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Thu, 9 Jul 2009 23:22:07 +0100 Subject: [PATCH 0942/1002] [ARM] 5598/1: ep93xx: core.c typesafe vic_init The EP93XX_VIC{1/2}_BASE defines are now typesafe due to [ARM] 5573/1: ep93xx: ensure typesafe io. The (void *) cast is not needed when calling vic_init(). Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index ce10f5b5dfbb9..68ac0545f570c 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -345,8 +345,8 @@ void __init ep93xx_init_irq(void) { int gpio_irq; - vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); - vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); for (gpio_irq = gpio_to_irq(0); gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { -- GitLab From d19d36672ee379f26b79df985a9a2e5afb3f1df1 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Fri, 10 Jul 2009 23:02:59 +0100 Subject: [PATCH 0943/1002] [ARM] 5599/1: MAINTAINERS: update for EP93XX ARM Change the maintainer of the EP93XX ARM ARCHITECTURE. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- MAINTAINERS | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index fa2a16def17af..7bf1128d74f4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -604,10 +604,14 @@ W: http://maxim.org.za/at91_26.html S: Maintained ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE -P: Lennert Buytenhek -M: kernel@wantstofly.org +P: Hartley Sweeten +M: hsweeten@visionengravers.com +P: Ryan Mallon +M: ryan@bluewatersys.com L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: arch/arm/mach-ep93xx/ +F: arch/arm/mach-ep93xx/include/mach/ ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT P: Lennert Buytenhek -- GitLab From 5b1c3c858cff4da95b9f7091eef424e706784cab Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Mon, 13 Jul 2009 19:50:10 +0100 Subject: [PATCH 0944/1002] [ARM] 5600/1: ep93xx: core.c remove cast when copying dev_addr The MAC address for the ep93xx ethernet driver can be optionally copied from registers in the controller when booting. Due to [ARM] 5573/1: ep93xx: ensure typesafe io, the cast for the source address is no longer needed. EP93XX_ETHERNET_BASE is typed as a (void __iomem __force *) so memcpy_fromio() needs to be used instead of memcpy(). Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 68ac0545f570c..4c38941a92c7d 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -541,10 +541,8 @@ static struct platform_device ep93xx_eth_device = { void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) { - if (copy_addr) { - memcpy(data->dev_addr, - (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); - } + if (copy_addr) + memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); ep93xx_eth_data = *data; platform_device_register(&ep93xx_eth_device); -- GitLab From 595c050d89e91e91cca3845e48b01042677bd19e Mon Sep 17 00:00:00 2001 From: Ryan Mallon <ryan@bluewatersys.com> Date: Wed, 15 Jul 2009 21:31:46 +0100 Subject: [PATCH 0945/1002] [ARM] 5605/1: Fix ep93xx gpio.c headers Fix a number of build errors in ep93xx gpio.c due to to missing irq.h Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/gpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 2d83d69e2eed0..1ea8871e03a96 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -18,6 +18,7 @@ #include <linux/seq_file.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/irq.h> #include <mach/hardware.h> -- GitLab From fbeeea5386ab213bd55b223f3a75c823fccd6df5 Mon Sep 17 00:00:00 2001 From: Ryan Mallon <ryan@bluewatersys.com> Date: Wed, 15 Jul 2009 21:51:59 +0100 Subject: [PATCH 0946/1002] [ARM] 5607/1: ep93xx: Use __iomem pointer on syscon write function Change the reg argument of the ep93xx_syscon_swlocked_write function to be an __iomem pointer. Fixes a number of build warnings. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/core.c | 2 +- arch/arm/mach-ep93xx/include/mach/platform.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 4c38941a92c7d..b390c35f8bc1a 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -377,7 +377,7 @@ void __init ep93xx_init_irq(void) */ static DEFINE_SPINLOCK(syscon_swlock); -void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg) +void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) { unsigned long flags; diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index fb5e59a3ea046..0af0a3ba70476 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -17,7 +17,7 @@ void ep93xx_init_irq(void); void ep93xx_init_time(unsigned long); /* EP93xx System Controller software locked register write */ -void ep93xx_syscon_swlocked_write(unsigned int val, unsigned int reg); +void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg); void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits); static inline void ep93xx_devcfg_set_bits(unsigned int bits) -- GitLab From 5d43f11bcf854d83b24c7ca6bb15d9ab9130159f Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Thu, 16 Jul 2009 22:46:31 +0100 Subject: [PATCH 0947/1002] [ARM] 5609/1: ep93xx: add register defines for keypad support Add missing register defines for ep93xx keypad clock support. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 087d22b8f3511..a11ae779baa0c 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -206,6 +206,11 @@ #define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) #define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) #define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) +#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) +#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) +#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) +#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN (1<<15) +#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0) #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) -- GitLab From d2c241955095b129459985a8c02d85b70984b945 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Tue, 14 Jul 2009 15:09:54 +0100 Subject: [PATCH 0948/1002] [ARM] 5601/1: Add HAVE_CLK depends on for w90p910 platform Add HAVE_CLK depends on for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index aef63c8e3d2dc..c3fed1ee7304c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -493,6 +493,7 @@ config ARCH_W90X900 select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB select GENERIC_GPIO + select HAVE_CLK select COMMON_CLKDEV help Support for Nuvoton (Winbond logic dept.) ARM9 processor,You -- GitLab From db58e90fdbe9d12b431ae8d8e856961ce75d74f0 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Tue, 14 Jul 2009 15:10:43 +0100 Subject: [PATCH 0949/1002] [ARM] 5602/1: Add sub clock api for w90p910 platform Add sub clock api for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/clock.c | 18 ++++++++++++++++++ arch/arm/mach-w90x900/clock.h | 8 ++++++++ arch/arm/mach-w90x900/w90p910.c | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c index f420613cd395d..49cf1fbc14eb4 100644 --- a/arch/arm/mach-w90x900/clock.c +++ b/arch/arm/mach-w90x900/clock.c @@ -25,6 +25,8 @@ #include "clock.h" +#define SUBCLK 0x24 + static DEFINE_SPINLOCK(clocks_lock); int clk_enable(struct clk *clk) @@ -68,6 +70,22 @@ void w90x900_clk_enable(struct clk *clk, int enable) __raw_writel(clken, W90X900_VA_CLKPWR); } +void w90x900_subclk_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->cken; + unsigned long clken; + + clken = __raw_readl(W90X900_VA_CLKPWR + SUBCLK); + + if (enable) + clken |= clocks; + else + clken &= ~clocks; + + __raw_writel(clken, W90X900_VA_CLKPWR + SUBCLK); +} + + void clks_register(struct clk_lookup *clks, size_t num) { int i; diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h index 4f27bda76d56c..d2f0e50a70bfa 100644 --- a/arch/arm/mach-w90x900/clock.h +++ b/arch/arm/mach-w90x900/clock.h @@ -13,6 +13,7 @@ #include <asm/clkdev.h> void w90x900_clk_enable(struct clk *clk, int enable); +void w90x900_subclk_enable(struct clk *clk, int enable); void clks_register(struct clk_lookup *clks, size_t num); struct clk { @@ -27,6 +28,13 @@ struct clk clk_##_name = { \ .cken = (1 << _ctrlbit), \ } +#define DEFINE_SUBCLK(_name, _ctrlbit) \ +struct clk clk_##_name = { \ + .enable = w90x900_subclk_enable, \ + .cken = (1 << _ctrlbit), \ + } + + #define DEF_CLKLOOK(_clk, _devname, _conname) \ { \ .clk = _clk, \ diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index 1c97e4930b7ab..1bde69eac3df9 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c @@ -57,9 +57,12 @@ static struct map_desc w90p910_iodesc[] __initdata = { static DEFINE_CLK(lcd, 0); static DEFINE_CLK(audio, 1); static DEFINE_CLK(fmi, 4); +static DEFINE_SUBCLK(ms, 0); +static DEFINE_SUBCLK(sd, 1); static DEFINE_CLK(dmac, 5); static DEFINE_CLK(atapi, 6); static DEFINE_CLK(emc, 7); +static DEFINE_SUBCLK(rmii, 2); static DEFINE_CLK(usbd, 8); static DEFINE_CLK(usbh, 9); static DEFINE_CLK(g2d, 10);; @@ -75,9 +78,12 @@ static struct clk_lookup w90p910_clkregs[] = { DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), DEF_CLKLOOK(&clk_audio, "w90p910-audio", NULL), DEF_CLKLOOK(&clk_fmi, "w90p910-fmi", NULL), + DEF_CLKLOOK(&clk_ms, "w90p910-fmi", "MS"), + DEF_CLKLOOK(&clk_sd, "w90p910-fmi", "SD"), DEF_CLKLOOK(&clk_dmac, "w90p910-dmac", NULL), DEF_CLKLOOK(&clk_atapi, "w90p910-atapi", NULL), DEF_CLKLOOK(&clk_emc, "w90p910-emc", NULL), + DEF_CLKLOOK(&clk_rmii, "w90p910-emc", "RMII"), DEF_CLKLOOK(&clk_usbd, "w90p910-usbd", NULL), DEF_CLKLOOK(&clk_usbh, "w90p910-usbh", NULL), DEF_CLKLOOK(&clk_g2d, "w90p910-g2d", NULL), -- GitLab From 0abe1856bdb68ef699c00949cf9f81fbec98d499 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Tue, 14 Jul 2009 15:12:26 +0100 Subject: [PATCH 0950/1002] [ARM] 5604/1: Add keypad multi-function pin api for w90p910 platform Add keypad multi-function pin api for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mfp-w90p910.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-w90x900/mfp-w90p910.c b/arch/arm/mach-w90x900/mfp-w90p910.c index a3520fefb5e73..8aec34b044ca1 100644 --- a/arch/arm/mach-w90x900/mfp-w90p910.c +++ b/arch/arm/mach-w90x900/mfp-w90p910.c @@ -90,7 +90,7 @@ void mfp_set_groupc(struct device *dev) } EXPORT_SYMBOL(mfp_set_groupc); -void mfp_set_groupi(struct device *dev, int gpio) +void mfp_set_groupi(struct device *dev) { unsigned long mfpen; const char *dev_id; @@ -103,10 +103,14 @@ void mfp_set_groupi(struct device *dev, int gpio) mfpen = __raw_readl(REG_MFSEL); + mfpen &= ~GPSELEI1;/*default gpio16*/ + if (strcmp(dev_id, "w90p910-wdog") == 0) mfpen |= GPSELEI1;/*enable wdog*/ else if (strcmp(dev_id, "w90p910-atapi") == 0) mfpen |= GPSELEI0;/*enable atapi*/ + else if (strcmp(dev_id, "w90p910-keypad") == 0) + mfpen &= ~GPSELEI0;/*enable keypad*/ __raw_writel(mfpen, REG_MFSEL); -- GitLab From 3aa7a9a3cf8774f6701b1903a6353f9545f561ce Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Mon, 20 Jul 2009 18:22:36 +0100 Subject: [PATCH 0951/1002] [ARM] 5612/1: ep93xx: add platform LEDs The EP93xx has two gpio pins specifically assigned to drive external LEDs. Add core support for these LEDs. On the EDB93xx development boards, the rdled is connected to an external reset circuit. Turning this led on for an extended amount of time will cause the circuit to issue a manual reset. Refer to Cirrus App Note AN258 for more information. http://www.cirrus.com/en/pubs/appNote/AN258REV2.pdf This led can be safely used as the system heartbeat with the ledtrig-heartbeat driver. echo heartbeat > /sys/class/leds/platform:rdled/trigger The grled can be used for any desired purpose. Tested-by: Matthieu Crapet <mcrapet@gmail.com> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/core.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index b390c35f8bc1a..2b58df0184c1e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -22,6 +22,7 @@ #include <linux/timex.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/leds.h> #include <linux/termios.h> #include <linux/amba/bus.h> #include <linux/amba/serial.h> @@ -568,6 +569,34 @@ void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) platform_device_register(&ep93xx_i2c_device); } + +/************************************************************************* + * EP93xx LEDs + *************************************************************************/ +static struct gpio_led ep93xx_led_pins[] = { + { + .name = "platform:grled", + .gpio = EP93XX_GPIO_LINE_GRLED, + }, { + .name = "platform:rdled", + .gpio = EP93XX_GPIO_LINE_RDLED, + }, +}; + +static struct gpio_led_platform_data ep93xx_led_data = { + .num_leds = ARRAY_SIZE(ep93xx_led_pins), + .leds = ep93xx_led_pins, +}; + +static struct platform_device ep93xx_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &ep93xx_led_data, + }, +}; + + extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) @@ -583,4 +612,5 @@ void __init ep93xx_init_devices(void) platform_device_register(&ep93xx_rtc_device); platform_device_register(&ep93xx_ohci_device); + platform_device_register(&ep93xx_leds); } -- GitLab From 4bf1fa5a34aa2dd0d2cc58f0fc213a2e22d007a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> Date: Tue, 21 Jul 2009 09:56:27 +0100 Subject: [PATCH 0952/1002] [ARM] 5613/1: implement CALLER_ADDRESSx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> As __builtin_return_address(n) doesn't work for ARM with n > 0, the kernel needs its own implementation. This fixes many warnings saying: warning: unsupported argument to '__builtin_return_address' The new methods and walk_stackframe must not be instrumented because CALLER_ADDRESSx is used in the various tracers and tracing the tracer is a bad idea. What's currently missing is an implementation using unwind tables. This is not fatal though, it's just that the tracers don't get enough information to be really useful. Note that if both ARM_UNWIND and FRAME_POINTER are enabled, walk_stackframe uses unwind information. So in this case the same implementation is used as when FRAME_POINTER is disabled. Cc: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/ftrace.h | 34 +++++++++++++++ arch/arm/kernel/Makefile | 4 +- arch/arm/kernel/return_address.c | 71 ++++++++++++++++++++++++++++++++ arch/arm/kernel/stacktrace.c | 4 +- 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 arch/arm/kernel/return_address.c diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index 39c8bc1a006af..d74265cffd86d 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -11,4 +11,38 @@ extern void mcount(void); #endif +#ifndef __ASSEMBLY__ + +#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) +/* + * return_address uses walk_stackframe to do it's work. If both + * CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind + * information. For this to work in the function tracer many functions would + * have to be marked with __notrace. So for now just depend on + * !CONFIG_ARM_UNWIND. + */ + +void *return_address(unsigned int); + +#else + +extern inline void *return_address(unsigned int level) +{ + return NULL; +} + +#endif + +#define HAVE_ARCH_CALLER_ADDR + +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) +#define CALLER_ADDR1 ((unsigned long)return_address(1)) +#define CALLER_ADDR2 ((unsigned long)return_address(2)) +#define CALLER_ADDR3 ((unsigned long)return_address(3)) +#define CALLER_ADDR4 ((unsigned long)return_address(4)) +#define CALLER_ADDR5 ((unsigned long)return_address(5)) +#define CALLER_ADDR6 ((unsigned long)return_address(6)) + +#endif /* ifndef __ASSEMBLY__ */ + #endif /* _ASM_ARM_FTRACE */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index ff89d0b3abc50..3213c9382b171 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -8,10 +8,12 @@ ifdef CONFIG_DYNAMIC_FTRACE CFLAGS_REMOVE_ftrace.o = -pg endif +CFLAGS_REMOVE_return_address.o = -pg + # Object file lists. obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \ - process.o ptrace.o setup.o signal.o \ + process.o ptrace.o return_address.o setup.o signal.o \ sys_arm.o stacktrace.o time.o traps.o obj-$(CONFIG_ISA_DMA_API) += dma.o diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c new file mode 100644 index 0000000000000..df246da4ceca2 --- /dev/null +++ b/arch/arm/kernel/return_address.c @@ -0,0 +1,71 @@ +/* + * arch/arm/kernel/return_address.c + * + * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> + * for Pengutronix + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include <linux/module.h> + +#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) +#include <linux/sched.h> + +#include <asm/stacktrace.h> + +struct return_address_data { + unsigned int level; + void *addr; +}; + +static int save_return_addr(struct stackframe *frame, void *d) +{ + struct return_address_data *data = d; + + if (!data->level) { + data->addr = (void *)frame->lr; + + return 1; + } else { + --data->level; + return 0; + } +} + +void *return_address(unsigned int level) +{ + struct return_address_data data; + struct stackframe frame; + register unsigned long current_sp asm ("sp"); + + data.level = level + 1; + + frame.fp = (unsigned long)__builtin_frame_address(0); + frame.sp = current_sp; + frame.lr = (unsigned long)__builtin_return_address(0); + frame.pc = (unsigned long)return_address; + + walk_stackframe(&frame, save_return_addr, &data); + + if (!data.level) + return data.addr; + else + return NULL; +} + +#else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */ + +#if defined(CONFIG_ARM_UNWIND) +#warning "TODO: return_address should use unwind tables" +#endif + +void *return_address(unsigned int level) +{ + return NULL; +} + +#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) / else */ + +EXPORT_SYMBOL_GPL(return_address); diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 9f444e5cc1650..20b7411e47fde 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -21,7 +21,7 @@ * Note that with framepointer enabled, even the leaf functions have the same * prologue and epilogue, therefore we can ignore the LR value in this case. */ -int unwind_frame(struct stackframe *frame) +int notrace unwind_frame(struct stackframe *frame) { unsigned long high, low; unsigned long fp = frame->fp; @@ -43,7 +43,7 @@ int unwind_frame(struct stackframe *frame) } #endif -void walk_stackframe(struct stackframe *frame, +void notrace walk_stackframe(struct stackframe *frame, int (*fn)(struct stackframe *, void *), void *data) { while (1) { -- GitLab From 42ff4cf957b695250534e540375e23507c722327 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 17 Jul 2009 14:42:33 +0100 Subject: [PATCH 0953/1002] [ARM] 5610/1: Add fmi resource define for w90p910 platform Add fmi resource define for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mach-w90p910evb.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c index 7a62bd348e80d..3b9fa312d9f51 100644 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -228,6 +228,28 @@ struct platform_device w90x900_device_usbgadget = { }; EXPORT_SYMBOL(w90x900_device_usbgadget); +/* FMI Device */ + +static struct resource w90p910_fmi_resource[] = { + [0] = { + .start = W90X900_PA_FMI, + .end = W90X900_PA_FMI + W90X900_SZ_FMI - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_FMI, + .end = IRQ_FMI, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device w90p910_device_fmi = { + .name = "w90p910-fmi", + .id = -1, + .num_resources = ARRAY_SIZE(w90p910_fmi_resource), + .resource = w90p910_fmi_resource, +}; + static struct map_desc w90p910_iodesc[] __initdata = { }; @@ -242,6 +264,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = { &w90x900_device_rtc, &w90x900_device_kpi, &w90x900_device_usbgadget, + &w90p910_device_fmi, }; static void __init w90p910evb_map_io(void) -- GitLab From 768db4e04b4c969cf3a9e81a79a10af6468ca56d Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Thu, 23 Jul 2009 08:47:57 +0100 Subject: [PATCH 0954/1002] [ARM] 5616/1: Add mac resource define for w90p910 mac driver Add mac resource define for w90p910 mac driver. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mach-w90p910evb.c | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c index 3b9fa312d9f51..2e56d84c6323e 100644 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -250,6 +250,38 @@ static struct platform_device w90p910_device_fmi = { .resource = w90p910_fmi_resource, }; +/* MAC device */ + +static struct resource w90x900_emc_resource[] = { + [0] = { + .start = W90X900_PA_EMC, + .end = W90X900_PA_EMC + W90X900_SZ_EMC - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_EMCTX, + .end = IRQ_EMCTX, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_EMCRX, + .end = IRQ_EMCRX, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 w90x900_device_emc_dmamask = 0xffffffffUL; +static struct platform_device w90p910_device_emc = { + .name = "w90p910-emc", + .id = -1, + .num_resources = ARRAY_SIZE(w90x900_emc_resource), + .resource = w90x900_emc_resource, + .dev = { + .dma_mask = &w90x900_device_emc_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + static struct map_desc w90p910_iodesc[] __initdata = { }; @@ -265,6 +297,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = { &w90x900_device_kpi, &w90x900_device_usbgadget, &w90p910_device_fmi, + &w90p910_device_emc, }; static void __init w90p910evb_map_io(void) -- GitLab From b48147663b2582bfb91a2bf39f9d1ffe8f209122 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Thu, 23 Jul 2009 08:50:20 +0100 Subject: [PATCH 0955/1002] [ARM] 5617/1: rename this spi device as w90p910-spi When programming clock api, I named this spi device as w90p910-usi, now, I think named it as w90p910-spi better Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/w90p910.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index 1bde69eac3df9..6ebf5cfc78daa 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c @@ -93,7 +93,7 @@ static struct clk_lookup w90p910_clkregs[] = { DEF_CLKLOOK(&clk_wdt, "w90p910-wdt", NULL), DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), - DEF_CLKLOOK(&clk_usi, "w90p910-usi", NULL), + DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), }; /* Initial serial platform data */ -- GitLab From c16d5d5657294e782d505efd00bbf2452d6aa0ca Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Thu, 23 Jul 2009 08:51:46 +0100 Subject: [PATCH 0956/1002] [ARM] 5618/1: Add spi resource define for w90p910 spi driver Add spi resource define for w90p910 spi driver. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mach-w90p910evb.c | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c index 2e56d84c6323e..3e3a267b2dde5 100644 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -20,7 +20,13 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/platform_device.h> + #include <linux/mtd/physmap.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -35,6 +41,8 @@ #define W90P910_FLASH_BASE 0xA0000000 #define W90P910_FLASH_SIZE 0x400000 +#define SPIOFFSET 0x200 +#define SPIOREG_SIZE 0x100 static struct mtd_partition w90p910_flash_partitions[] = { { @@ -282,6 +290,56 @@ static struct platform_device w90p910_device_emc = { } }; +/* SPI device */ + +static struct resource w90p910_spi_resource[] = { + [0] = { + .start = W90X900_PA_I2C + SPIOFFSET, + .end = W90X900_PA_I2C + SPIOFFSET + SPIOREG_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SSP, + .end = IRQ_SSP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device w90p910_device_spi = { + .name = "w90p910-spi", + .id = -1, + .num_resources = ARRAY_SIZE(w90p910_spi_resource), + .resource = w90p910_spi_resource, +}; + +/* spi device, spi flash info */ + +static struct mtd_partition w90p910_spi_flash_partitions[] = { + { + .name = "bootloader(spi)", + .size = 0x0100000, + .offset = 0, + }, +}; + +static struct flash_platform_data w90p910_spi_flash_data = { + .name = "m25p80", + .parts = w90p910_spi_flash_partitions, + .nr_parts = ARRAY_SIZE(w90p910_spi_flash_partitions), + .type = "w25x16", +}; + +static struct spi_board_info w90p910_spi_board_info[] __initdata = { + { + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &w90p910_spi_flash_data, + .mode = SPI_MODE_0, + }, +}; + static struct map_desc w90p910_iodesc[] __initdata = { }; @@ -298,6 +356,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = { &w90x900_device_usbgadget, &w90p910_device_fmi, &w90p910_device_emc, + &w90p910_device_spi, }; static void __init w90p910evb_map_io(void) @@ -309,6 +368,8 @@ static void __init w90p910evb_map_io(void) static void __init w90p910evb_init(void) { platform_add_devices(w90p910evb_dev, ARRAY_SIZE(w90p910evb_dev)); + spi_register_board_info(w90p910_spi_board_info, + ARRAY_SIZE(w90p910_spi_board_info)); } MACHINE_START(W90P910EVB, "W90P910EVB") -- GitLab From 3f3f1d9d8de10a5dad0d22046cdd26dfb93d05c9 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Thu, 23 Jul 2009 08:52:51 +0100 Subject: [PATCH 0957/1002] [ARM] 5619/1: Add spi mfp api for w90p910 spi driver Add spi mfp api for w90p910 spi driver. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mfp-w90p910.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/arm/mach-w90x900/mfp-w90p910.c b/arch/arm/mach-w90x900/mfp-w90p910.c index 8aec34b044ca1..e11a32b6856d7 100644 --- a/arch/arm/mach-w90x900/mfp-w90p910.c +++ b/arch/arm/mach-w90x900/mfp-w90p910.c @@ -34,6 +34,12 @@ #define GPSELEI0 (0x01 << 26) #define GPSELEI1 (0x01 << 27) +#define GPIOG0TO1 (0x03 << 14) +#define GPIOG2TO3 (0x03 << 16) +#define ENSPI (0x0a << 14) +#define ENI2C0 (0x01 << 14) +#define ENI2C1 (0x01 << 16) + static DECLARE_MUTEX(mfp_sem); void mfp_set_groupf(struct device *dev) @@ -118,3 +124,35 @@ void mfp_set_groupi(struct device *dev) } EXPORT_SYMBOL(mfp_set_groupi); +void mfp_set_groupg(struct device *dev) +{ + unsigned long mfpen; + const char *dev_id; + + BUG_ON(!dev); + + down(&mfp_sem); + + dev_id = dev_name(dev); + + mfpen = __raw_readl(REG_MFSEL); + + if (strcmp(dev_id, "w90p910-spi") == 0) { + mfpen &= ~(GPIOG0TO1 | GPIOG2TO3); + mfpen |= ENSPI;/*enable spi*/ + } else if (strcmp(dev_id, "w90p910-i2c0") == 0) { + mfpen &= ~(GPIOG0TO1); + mfpen |= ENI2C0;/*enable i2c0*/ + } else if (strcmp(dev_id, "w90p910-i2c1") == 0) { + mfpen &= ~(GPIOG2TO3); + mfpen |= ENI2C1;/*enable i2c1*/ + } else { + mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/ + } + + __raw_writel(mfpen, REG_MFSEL); + + up(&mfp_sem); +} +EXPORT_SYMBOL(mfp_set_groupg); + -- GitLab From 915190f7d4f08e413e5fde6b0abcd5375aeacdf4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Tue, 21 Jul 2009 11:31:29 +0100 Subject: [PATCH 0958/1002] [ARM] 5614/1: at91: atmel_lcdfb: add at91sam9g10 support to atmel LCD driver Modify atmel LCD driver: atmel_lcdfb for at91sam9g10. This add a clock management equivalent to at91sam9261. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- drivers/video/Kconfig | 4 ++-- drivers/video/atmel_lcdfb.c | 6 ++++-- drivers/video/backlight/Kconfig | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 36281823fe542..f632c6682aa66 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -933,7 +933,7 @@ config FB_S1D13XXX config FB_ATMEL tristate "AT91/AT32 LCD Controller support" - depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32) + depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9G10 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -949,7 +949,7 @@ config FB_INTSRAM config FB_ATMEL_STN bool "Use a STN display with AT91/AT32 LCD Controller" - depends on FB_ATMEL && MACH_AT91SAM9261EK + depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK) default n help Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5afd64482f558..adc5bf01254c6 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -182,7 +182,8 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) { unsigned long value; - if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000())) + if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() + || cpu_is_at32ap7000())) return xres; value = xres; @@ -821,7 +822,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) info->fix = atmel_lcdfb_fix; /* Enable LCDC Clocks */ - if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() + || cpu_is_at32ap7000()) { sinfo->bus_clk = clk_get(dev, "hck1"); if (IS_ERR(sinfo->bus_clk)) { ret = PTR_ERR(sinfo->bus_clk); diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index f9d19be05540a..90861cd931651 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -110,7 +110,7 @@ config BACKLIGHT_CLASS_DEVICE config BACKLIGHT_ATMEL_LCDC bool "Atmel LCDC Contrast-as-Backlight control" depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL - default y if MACH_SAM9261EK || MACH_SAM9263EK + default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK help This provides a backlight control internal to the Atmel LCDC driver. If the LCD "contrast control" on your board is wired -- GitLab From 4c8abb556b393b3ed73d72481ba27705294f6dc6 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Fri, 24 Jul 2009 12:16:57 +0100 Subject: [PATCH 0959/1002] ARM: 5622/1: at91: at91sam9g45 headers: DMA peripheral identifiers It adds DMA peripheral identifiers for hardware handshaking interface. It will be used in platform code. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/include/mach/at91sam9g45.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h index 2c42cf5f0c549..a526869aee377 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9g45.h +++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h @@ -135,4 +135,21 @@ #define CONSISTENT_DMA_SIZE SZ_4M +/* + * DMA peripheral identifiers + * for hardware handshaking interface + */ +#define AT_DMA_ID_MCI0 0 +#define AT_DMA_ID_SPI0_TX 1 +#define AT_DMA_ID_SPI0_RX 2 +#define AT_DMA_ID_SPI1_TX 3 +#define AT_DMA_ID_SPI1_RX 4 +#define AT_DMA_ID_SSC0_TX 5 +#define AT_DMA_ID_SSC0_RX 6 +#define AT_DMA_ID_SSC1_TX 7 +#define AT_DMA_ID_SSC1_RX 8 +#define AT_DMA_ID_AC97_TX 9 +#define AT_DMA_ID_AC97_RX 10 +#define AT_DMA_ID_MCI1 13 + #endif -- GitLab From ef12379f205bed7e92434e12ddd44e62d13bebe1 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten <hartleys@visionengravers.com> Date: Wed, 29 Jul 2009 22:41:06 +0100 Subject: [PATCH 0960/1002] ARM: 5628/1: ep93xx: Introduce Pulse Width Modulator (PWM) driver The EP93xx features two PWMs (one on the EP9307) with the following features: * Configurable dual output * Separate input clocks for each PWM output * 16-bit resolution * Programmable pulse width (duty cycle), interval (frequency), and polarity This adds the necessary core support as well as the driver. A sysfs interface is provided to control the PWM outputs. Signed-off-by: Matthieu Crapet <mcrapet@gmail.com> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/clock.c | 4 + arch/arm/mach-ep93xx/core.c | 85 ++++ .../mach-ep93xx/include/mach/ep93xx-regs.h | 1 + arch/arm/mach-ep93xx/include/mach/platform.h | 4 + drivers/misc/Kconfig | 13 + drivers/misc/Makefile | 1 + drivers/misc/ep93xx_pwm.c | 384 ++++++++++++++++++ 7 files changed, 492 insertions(+) create mode 100644 drivers/misc/ep93xx_pwm.c diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index b6b53447b1b47..3dd0e2a23095c 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -72,6 +72,9 @@ static struct clk clk_keypad = { .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN, .set_rate = set_keytchclk_rate, }; +static struct clk clk_pwm = { + .rate = EP93XX_EXT_CLK_RATE, +}; /* DMA Clocks */ static struct clk clk_m2p0 = { @@ -137,6 +140,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "pll2", &clk_pll2), INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), + INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), INIT_CK(NULL, "m2p2", &clk_m2p2), diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 2b58df0184c1e..40755298fa330 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -597,6 +597,91 @@ static struct platform_device ep93xx_leds = { }; +/************************************************************************* + * EP93xx pwm peripheral handling + *************************************************************************/ +static struct resource ep93xx_pwm0_resource[] = { + { + .start = EP93XX_PWM_PHYS_BASE, + .end = EP93XX_PWM_PHYS_BASE + 0x10 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_pwm0_device = { + .name = "ep93xx-pwm", + .id = 0, + .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), + .resource = ep93xx_pwm0_resource, +}; + +static struct resource ep93xx_pwm1_resource[] = { + { + .start = EP93XX_PWM_PHYS_BASE + 0x20, + .end = EP93XX_PWM_PHYS_BASE + 0x30 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_pwm1_device = { + .name = "ep93xx-pwm", + .id = 1, + .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), + .resource = ep93xx_pwm1_resource, +}; + +void __init ep93xx_register_pwm(int pwm0, int pwm1) +{ + if (pwm0) + platform_device_register(&ep93xx_pwm0_device); + + /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ + if (pwm1) + platform_device_register(&ep93xx_pwm1_device); +} + +int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) +{ + int err; + + if (pdev->id == 0) { + err = 0; + } else if (pdev->id == 1) { + err = gpio_request(EP93XX_GPIO_LINE_EGPIO14, + dev_name(&pdev->dev)); + if (err) + return err; + err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0); + if (err) + goto fail; + + /* PWM 1 output on EGPIO[14] */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG); + } else { + err = -ENODEV; + } + + return err; + +fail: + gpio_free(EP93XX_GPIO_LINE_EGPIO14); + return err; +} +EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio); + +void ep93xx_pwm_release_gpio(struct platform_device *pdev) +{ + if (pdev->id == 1) { + gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14); + gpio_free(EP93XX_GPIO_LINE_EGPIO14); + + /* EGPIO[14] used for GPIO */ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG); + } +} +EXPORT_SYMBOL(ep93xx_pwm_release_gpio); + + extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index a11ae779baa0c..ea78e908fc82c 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -147,6 +147,7 @@ #define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000) #define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000) +#define EP93XX_PWM_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00110000) #define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000) #define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000) diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 0af0a3ba70476..5f5fa6574d342 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -5,6 +5,7 @@ #ifndef __ASSEMBLY__ struct i2c_board_info; +struct platform_device; struct ep93xx_eth_data { @@ -32,6 +33,9 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits) void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_i2c(struct i2c_board_info *devices, int num); +void ep93xx_register_pwm(int pwm0, int pwm1); +int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); +void ep93xx_pwm_release_gpio(struct platform_device *pdev); void ep93xx_init_devices(void); extern struct sys_timer ep93xx_timer; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 68ab39d7cb358..df1f86b5c83e4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -233,6 +233,19 @@ config ISL29003 This driver can also be built as a module. If so, the module will be called isl29003. +config EP93XX_PWM + tristate "EP93xx PWM support" + depends on ARCH_EP93XX + help + This option enables device driver support for the PWM channels + on the Cirrus EP93xx processors. The EP9307 chip only has one + PWM channel all the others have two, the second channel is an + alternate function of the EGPIO14 pin. A sysfs interface is + provided to control the PWM channels. + + To compile this driver as a module, choose M here: the module will + be called ep93xx_pwm. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 36f733cd60e65..f982d2ecfde7c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_SGI_XP) += sgi-xp/ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_HP_ILO) += hpilo.o obj-$(CONFIG_ISL29003) += isl29003.o +obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_C2PORT) += c2port/ obj-y += eeprom/ obj-y += cb710/ diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c new file mode 100644 index 0000000000000..ba4694169d796 --- /dev/null +++ b/drivers/misc/ep93xx_pwm.c @@ -0,0 +1,384 @@ +/* + * Simple PWM driver for EP93XX + * + * (c) Copyright 2009 Matthieu Crapet <mcrapet@gmail.com> + * (c) Copyright 2009 H Hartley Sweeten <hsweeten@visionengravers.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * EP9307 has only one channel: + * - PWMOUT + * + * EP9301/02/12/15 have two channels: + * - PWMOUT + * - PWMOUT1 (alternate function for EGPIO14) + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> + +#include <mach/platform.h> + +#define EP93XX_PWMx_TERM_COUNT 0x00 +#define EP93XX_PWMx_DUTY_CYCLE 0x04 +#define EP93XX_PWMx_ENABLE 0x08 +#define EP93XX_PWMx_INVERT 0x0C + +#define EP93XX_PWM_MAX_COUNT 0xFFFF + +struct ep93xx_pwm { + void __iomem *mmio_base; + struct clk *clk; + u32 duty_percent; +}; + +static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm, + unsigned int val, unsigned int off) +{ + __raw_writel(val, pwm->mmio_base + off); +} + +static inline unsigned int ep93xx_pwm_readl(struct ep93xx_pwm *pwm, + unsigned int off) +{ + return __raw_readl(pwm->mmio_base + off); +} + +static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value) +{ + ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_TERM_COUNT); +} + +static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) +{ + return ep93xx_pwm_readl(pwm, EP93XX_PWMx_TERM_COUNT); +} + +static inline void ep93xx_pwm_write_dc(struct ep93xx_pwm *pwm, u16 value) +{ + ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_DUTY_CYCLE); +} + +static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm) +{ + ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_ENABLE); +} + +static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm) +{ + ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_ENABLE); +} + +static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) +{ + return ep93xx_pwm_readl(pwm, EP93XX_PWMx_ENABLE) & 0x1; +} + +static inline void ep93xx_pwm_invert(struct ep93xx_pwm *pwm) +{ + ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_INVERT); +} + +static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm) +{ + ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_INVERT); +} + +static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) +{ + return ep93xx_pwm_readl(pwm, EP93XX_PWMx_INVERT) & 0x1; +} + +/* + * /sys/devices/platform/ep93xx-pwm.N + * /min_freq read-only minimum pwm output frequency + * /max_req read-only maximum pwm output frequency + * /freq read-write pwm output frequency (0 = disable output) + * /duty_percent read-write pwm duty cycle percent (1..99) + * /invert read-write invert pwm output + */ + +static ssize_t ep93xx_pwm_get_min_freq(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + unsigned long rate = clk_get_rate(pwm->clk); + + return sprintf(buf, "%ld\n", rate / (EP93XX_PWM_MAX_COUNT + 1)); +} + +static ssize_t ep93xx_pwm_get_max_freq(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + unsigned long rate = clk_get_rate(pwm->clk); + + return sprintf(buf, "%ld\n", rate / 2); +} + +static ssize_t ep93xx_pwm_get_freq(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + + if (ep93xx_pwm_is_enabled(pwm)) { + unsigned long rate = clk_get_rate(pwm->clk); + u16 term = ep93xx_pwm_read_tc(pwm); + + return sprintf(buf, "%ld\n", rate / (term + 1)); + } else { + return sprintf(buf, "disabled\n"); + } +} + +static ssize_t ep93xx_pwm_set_freq(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err) + return -EINVAL; + + if (val == 0) { + ep93xx_pwm_disable(pwm); + } else if (val <= (clk_get_rate(pwm->clk) / 2)) { + u32 term, duty; + + val = (clk_get_rate(pwm->clk) / val) - 1; + if (val > EP93XX_PWM_MAX_COUNT) + val = EP93XX_PWM_MAX_COUNT; + if (val < 1) + val = 1; + + term = ep93xx_pwm_read_tc(pwm); + duty = ((val + 1) * pwm->duty_percent / 100) - 1; + + /* If pwm is running, order is important */ + if (val > term) { + ep93xx_pwm_write_tc(pwm, val); + ep93xx_pwm_write_dc(pwm, duty); + } else { + ep93xx_pwm_write_dc(pwm, duty); + ep93xx_pwm_write_tc(pwm, val); + } + + if (!ep93xx_pwm_is_enabled(pwm)) + ep93xx_pwm_enable(pwm); + } else { + return -EINVAL; + } + + return count; +} + +static ssize_t ep93xx_pwm_get_duty_percent(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + + return sprintf(buf, "%d\n", pwm->duty_percent); +} + +static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err) + return -EINVAL; + + if (val > 0 && val < 100) { + u32 term = ep93xx_pwm_read_tc(pwm); + ep93xx_pwm_write_dc(pwm, ((term + 1) * val / 100) - 1); + pwm->duty_percent = val; + return count; + } + + return -EINVAL; +} + +static ssize_t ep93xx_pwm_get_invert(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + + return sprintf(buf, "%d\n", ep93xx_pwm_is_inverted(pwm)); +} + +static ssize_t ep93xx_pwm_set_invert(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + long val; + int err; + + err = strict_strtol(buf, 10, &val); + if (err) + return -EINVAL; + + if (val == 0) + ep93xx_pwm_normal(pwm); + else if (val == 1) + ep93xx_pwm_invert(pwm); + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL); +static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL); +static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO, + ep93xx_pwm_get_freq, ep93xx_pwm_set_freq); +static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO, + ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent); +static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO, + ep93xx_pwm_get_invert, ep93xx_pwm_set_invert); + +static struct attribute *ep93xx_pwm_attrs[] = { + &dev_attr_min_freq.attr, + &dev_attr_max_freq.attr, + &dev_attr_freq.attr, + &dev_attr_duty_percent.attr, + &dev_attr_invert.attr, + NULL +}; + +static const struct attribute_group ep93xx_pwm_sysfs_files = { + .attrs = ep93xx_pwm_attrs, +}; + +static int __init ep93xx_pwm_probe(struct platform_device *pdev) +{ + struct ep93xx_pwm *pwm; + struct resource *res; + int err; + + err = ep93xx_pwm_acquire_gpio(pdev); + if (err) + return err; + + pwm = kzalloc(sizeof(struct ep93xx_pwm), GFP_KERNEL); + if (!pwm) { + err = -ENOMEM; + goto fail_no_mem; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -ENXIO; + goto fail_no_mem_resource; + } + + res = request_mem_region(res->start, resource_size(res), pdev->name); + if (res == NULL) { + err = -EBUSY; + goto fail_no_mem_resource; + } + + pwm->mmio_base = ioremap(res->start, resource_size(res)); + if (pwm->mmio_base == NULL) { + err = -ENXIO; + goto fail_no_ioremap; + } + + err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); + if (err) + goto fail_no_sysfs; + + pwm->clk = clk_get(&pdev->dev, "pwm_clk"); + if (IS_ERR(pwm->clk)) { + err = PTR_ERR(pwm->clk); + goto fail_no_clk; + } + + pwm->duty_percent = 50; + + platform_set_drvdata(pdev, pwm); + + /* disable pwm at startup. Avoids zero value. */ + ep93xx_pwm_disable(pwm); + ep93xx_pwm_write_tc(pwm, EP93XX_PWM_MAX_COUNT); + ep93xx_pwm_write_dc(pwm, EP93XX_PWM_MAX_COUNT / 2); + + clk_enable(pwm->clk); + + return 0; + +fail_no_clk: + sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); +fail_no_sysfs: + iounmap(pwm->mmio_base); +fail_no_ioremap: + release_mem_region(res->start, resource_size(res)); +fail_no_mem_resource: + kfree(pwm); +fail_no_mem: + ep93xx_pwm_release_gpio(pdev); + return err; +} + +static int __exit ep93xx_pwm_remove(struct platform_device *pdev) +{ + struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + ep93xx_pwm_disable(pwm); + clk_disable(pwm->clk); + clk_put(pwm->clk); + platform_set_drvdata(pdev, NULL); + sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); + iounmap(pwm->mmio_base); + release_mem_region(res->start, resource_size(res)); + kfree(pwm); + ep93xx_pwm_release_gpio(pdev); + + return 0; +} + +static struct platform_driver ep93xx_pwm_driver = { + .driver = { + .name = "ep93xx-pwm", + .owner = THIS_MODULE, + }, + .remove = __exit_p(ep93xx_pwm_remove), +}; + +static int __init ep93xx_pwm_init(void) +{ + return platform_driver_probe(&ep93xx_pwm_driver, ep93xx_pwm_probe); +} + +static void __exit ep93xx_pwm_exit(void) +{ + platform_driver_unregister(&ep93xx_pwm_driver); +} + +module_init(ep93xx_pwm_init); +module_exit(ep93xx_pwm_exit); + +MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, " + "H Hartley Sweeten <hsweeten@visionengravers.com>"); +MODULE_DESCRIPTION("EP93xx PWM driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ep93xx-pwm"); -- GitLab From 41a353d126ca332c20cfd97683b6261992743840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20B=C3=A9nard?= <eric@eukrea.com> Date: Thu, 30 Jul 2009 07:20:03 +0100 Subject: [PATCH 0961/1002] ARM: 5629/1: Add support for Eukrea's CPU9260 & CPU9G20 CPU9260 and CPU9G20 share the same PCB populated with either Atmel's AT91SAM9260B or AT91SAM9G20B with up to 64MB Strataflash, up to 128MB SDRAM, up to 2GB NAND and an ethernet PHY in RMII mode. Signed-off-by: Eric Benard <eric@eukrea.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/configs/cpu9260_defconfig | 1338 +++++++++++++++++++++++++++ arch/arm/configs/cpu9g20_defconfig | 1328 ++++++++++++++++++++++++++ arch/arm/mach-at91/Kconfig | 14 + arch/arm/mach-at91/Makefile | 2 + arch/arm/mach-at91/board-cpu9krea.c | 385 ++++++++ 5 files changed, 3067 insertions(+) create mode 100644 arch/arm/configs/cpu9260_defconfig create mode 100644 arch/arm/configs/cpu9g20_defconfig create mode 100644 arch/arm/mach-at91/board-cpu9krea.c diff --git a/arch/arm/configs/cpu9260_defconfig b/arch/arm/configs/cpu9260_defconfig new file mode 100644 index 0000000000000..601e7f3d5e97d --- /dev/null +++ b/arch/arm/configs/cpu9260_defconfig @@ -0,0 +1,1338 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.31-rc3 +# Tue Jul 14 14:57:55 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_AT91SAM9260=y +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91SAM9260 Variants +# +# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set + +# +# AT91SAM9260 / AT91SAM9XE Board Type +# +# CONFIG_MACH_AT91SAM9260EK is not set +# CONFIG_MACH_CAM60 is not set +# CONFIG_MACH_SAM9_L9260 is not set +# CONFIG_MACH_AFEB9260 is not set +# CONFIG_MACH_USB_A9260 is not set +# CONFIG_MACH_QIL_A9260 is not set +CONFIG_MACH_CPU9260=y + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +CONFIG_MTD_NAND_ATMEL_ECC_HW=y +# CONFIG_MTD_NAND_ATMEL_ECC_SOFT is not set +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=y +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91SAM9X_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_AT91SAM9 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/cpu9g20_defconfig b/arch/arm/configs/cpu9g20_defconfig new file mode 100644 index 0000000000000..b5b9cbbc6977b --- /dev/null +++ b/arch/arm/configs/cpu9g20_defconfig @@ -0,0 +1,1328 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.31-rc3 +# Tue Jul 14 15:03:43 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +CONFIG_ARCH_AT91SAM9G20=y +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91SAM9G20 Board Type +# +# CONFIG_MACH_AT91SAM9G20EK is not set +CONFIG_MACH_CPU9G20=y + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set +CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=y +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91SAM9X_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_AT91SAM9 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 8f3e15abdb62b..83a89720ada9f 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -217,6 +217,13 @@ config MACH_QIL_A9260 Select this if you are using a Calao Systems QIL-A9260 Board. <http://www.calao-systems.com> +config MACH_CPU9260 + bool "Eukrea CPU9260 board" + depends on ARCH_AT91SAM9260 + help + Select this if you are using a Eukrea Electromatique's + CPU9260 Board <http://www.eukrea.com/> + endif # ---------------------------------------------------------- @@ -303,6 +310,13 @@ config MACH_AT91SAM9G20EK help Select this if you are using Atmel's AT91SAM9G20-EK Evaluation Kit. +config MACH_CPU9G20 + bool "Eukrea CPU9G20 board" + depends on ARCH_AT91SAM9G20 + help + Select this if you are using a Eukrea Electromatique's + CPU9G20 Board <http://www.eukrea.com/> + endif # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 4eaf80abe1009..b2ea2e5a88171 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_MACH_SAM9_L9260) += board-sam9-l9260.o obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o +obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o # AT91SAM9261 board-specific support obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o @@ -57,6 +58,7 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o # AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o +obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o # AT91SAM9G45 board-specific support obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c new file mode 100644 index 0000000000000..4bc2e9f6ebb53 --- /dev/null +++ b/arch/arm/mach-at91/board-cpu9krea.c @@ -0,0 +1,385 @@ +/* + * linux/arch/arm/mach-at91/board-cpu9krea.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * Copyright (C) 2009 Eric Benard - eric@eukrea.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/mtd/physmap.h> + +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9_smc.h> +#include <mach/at91sam9260_matrix.h> + +#include "sam9_smc.h" +#include "generic.h" + +static void __init cpu9krea_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | + ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR | + ATMEL_UART_DCD | ATMEL_UART_RI); + + /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | + ATMEL_UART_RTS); + + /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */ + at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | + ATMEL_UART_RTS); + + /* USART3 on ttyS4. (Rx, Tx) */ + at91_register_uart(AT91SAM9260_ID_US3, 4, 0); + + /* USART4 on ttyS5. (Rx, Tx) */ + at91_register_uart(AT91SAM9260_ID_US4, 5, 0); + + /* USART5 on ttyS6. (Rx, Tx) */ + at91_register_uart(AT91SAM9260_ID_US5, 6, 0); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init cpu9krea_init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata cpu9krea_usbh_data = { + .ports = 2, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata cpu9krea_udc_data = { + .vbus_pin = AT91_PIN_PC8, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata cpu9krea_macb_data = { + .is_rmii = 1, +}; + +/* + * NAND flash + */ +static struct atmel_nand_data __initdata cpu9krea_nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .bus_width_16 = 0, +}; + +#ifdef CONFIG_MACH_CPU9260 +static struct sam9_smc_config __initdata cpu9krea_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE + | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; +#else +static struct sam9_smc_config __initdata cpu9krea_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE + | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 3, +}; +#endif + +static void __init cpu9krea_add_device_nand(void) +{ + sam9_smc_configure(3, &cpu9krea_nand_smc_config); + at91_add_device_nand(&cpu9krea_nand_data); +} + +/* + * NOR flash + */ +static struct physmap_flash_data cpuat9260_nor_data = { + .width = 2, +}; + +#define NOR_BASE AT91_CHIPSELECT_0 +#define NOR_SIZE SZ_64M + +static struct resource nor_flash_resources[] = { + { + .start = NOR_BASE, + .end = NOR_BASE + NOR_SIZE - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device cpu9krea_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &cpuat9260_nor_data, + }, + .resource = nor_flash_resources, + .num_resources = ARRAY_SIZE(nor_flash_resources), +}; + +#ifdef CONFIG_MACH_CPU9260 +static struct sam9_smc_config __initdata cpu9krea_nor_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 10, + .nrd_pulse = 10, + .ncs_write_pulse = 6, + .nwe_pulse = 6, + + .read_cycle = 12, + .write_cycle = 8, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE + | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE + | AT91_SMC_DBW_16, + .tdf_cycles = 2, +}; +#else +static struct sam9_smc_config __initdata cpu9krea_nor_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 13, + .nrd_pulse = 13, + .ncs_write_pulse = 8, + .nwe_pulse = 8, + + .read_cycle = 15, + .write_cycle = 10, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE + | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE + | AT91_SMC_DBW_16, + .tdf_cycles = 2, +}; +#endif + +static __init void cpu9krea_add_device_nor(void) +{ + unsigned long csa; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_VDDIOMSEL_3_3V); + + /* configure chip-select 0 (NOR) */ + sam9_smc_configure(0, &cpu9krea_nor_smc_config); + + platform_device_register(&cpu9krea_nor_flash); +} + +/* + * LEDs + */ +static struct gpio_led cpu9krea_leds[] = { + { /* LED1 */ + .name = "LED1", + .gpio = AT91_PIN_PC11, + .active_low = 1, + .default_trigger = "timer", + }, + { /* LED2 */ + .name = "LED2", + .gpio = AT91_PIN_PC12, + .active_low = 1, + .default_trigger = "heartbeat", + }, + { /* LED3 */ + .name = "LED3", + .gpio = AT91_PIN_PC7, + .active_low = 1, + .default_trigger = "none", + }, + { /* LED4 */ + .name = "LED4", + .gpio = AT91_PIN_PC9, + .active_low = 1, + .default_trigger = "none", + } +}; + +static struct i2c_board_info __initdata cpu9krea_i2c_devices[] = { + { + I2C_BOARD_INFO("rtc-ds1307", 0x68), + .type = "ds1339", + }, +}; + +/* + * GPIO Buttons + */ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button cpu9krea_buttons[] = { + { + .gpio = AT91_PIN_PC3, + .code = BTN_0, + .desc = "BP1", + .active_low = 1, + .wakeup = 1, + }, + { + .gpio = AT91_PIN_PB20, + .code = BTN_1, + .desc = "BP2", + .active_low = 1, + .wakeup = 1, + } +}; + +static struct gpio_keys_platform_data cpu9krea_button_data = { + .buttons = cpu9krea_buttons, + .nbuttons = ARRAY_SIZE(cpu9krea_buttons), +}; + +static struct platform_device cpu9krea_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &cpu9krea_button_data, + } +}; + +static void __init cpu9krea_add_device_buttons(void) +{ + at91_set_gpio_input(AT91_PIN_PC3, 1); /* BP1 */ + at91_set_deglitch(AT91_PIN_PC3, 1); + at91_set_gpio_input(AT91_PIN_PB20, 1); /* BP2 */ + at91_set_deglitch(AT91_PIN_PB20, 1); + + platform_device_register(&cpu9krea_button_device); +} +#else +static void __init cpu9krea_add_device_buttons(void) +{ +} +#endif + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata cpu9krea_mmc_data = { + .slot_b = 0, + .wire4 = 1, + .det_pin = AT91_PIN_PA29, +}; + +static void __init cpu9krea_board_init(void) +{ + /* NOR */ + cpu9krea_add_device_nor(); + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&cpu9krea_usbh_data); + /* USB Device */ + at91_add_device_udc(&cpu9krea_udc_data); + /* NAND */ + cpu9krea_add_device_nand(); + /* Ethernet */ + at91_add_device_eth(&cpu9krea_macb_data); + /* MMC */ + at91_add_device_mmc(0, &cpu9krea_mmc_data); + /* I2C */ + at91_add_device_i2c(cpu9krea_i2c_devices, + ARRAY_SIZE(cpu9krea_i2c_devices)); + /* LEDs */ + at91_gpio_leds(cpu9krea_leds, ARRAY_SIZE(cpu9krea_leds)); + /* Push Buttons */ + cpu9krea_add_device_buttons(); +} + +#ifdef CONFIG_MACH_CPU9260 +MACHINE_START(CPUAT9260, "Eukrea CPU9260") +#else +MACHINE_START(CPUAT9G20, "Eukrea CPU9G20") +#endif + /* Maintainer: Eric Benard - EUKREA Electromatique */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = cpu9krea_map_io, + .init_irq = cpu9krea_init_irq, + .init_machine = cpu9krea_board_init, +MACHINE_END -- GitLab From 10233a939812450e4fe07cf529585bab5b4d99ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20B=C3=A9nard?= <eric@eukrea.com> Date: Thu, 30 Jul 2009 07:23:42 +0100 Subject: [PATCH 0962/1002] ARM: 5630/1: Add support for Eukrea's CPUAT91 CPUAT91 is based on Atmel's AT91RM9200 with up to 16MB Strataflash, up to 128MB SDRAM and an ethernet PHY in RMII mode. Signed-off-by: Eric Benard <ebenard@eukrea.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/configs/cpuat91_defconfig | 1316 ++++++++++++++++++++++++++++ arch/arm/mach-at91/Kconfig | 7 + arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/board-cpuat91.c | 185 ++++ 4 files changed, 1509 insertions(+) create mode 100644 arch/arm/configs/cpuat91_defconfig create mode 100644 arch/arm/mach-at91/board-cpuat91.c diff --git a/arch/arm/configs/cpuat91_defconfig b/arch/arm/configs/cpuat91_defconfig new file mode 100644 index 0000000000000..4901827253fbe --- /dev/null +++ b/arch/arm/configs/cpuat91_defconfig @@ -0,0 +1,1316 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.31-rc3 +# Tue Jul 14 14:45:01 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +CONFIG_ARCH_AT91RM9200=y +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91RM9200 Board Type +# +# CONFIG_MACH_ONEARM is not set +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_ATEB9200 is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_PICOTUX2XX is not set +# CONFIG_MACH_KAFA is not set +# CONFIG_MACH_ECBAT91 is not set +# CONFIG_MACH_YL9200 is not set +CONFIG_MACH_CPUAT91=y + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4T=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=y +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91RM9200_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_AT91RM9200 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 83a89720ada9f..a24d824c428b3 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -156,6 +156,13 @@ config MACH_YL9200 help Select this if you are using the ucDragon YL-9200 board. +config MACH_CPUAT91 + bool "Eukrea CPUAT91" + depends on ARCH_AT91RM9200 + help + Select this if you are using the Eukrea Electromatique's + CPUAT91 board <http://www.eukrea.com/>. + endif # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index b2ea2e5a88171..a6ed015d82edc 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_KAFA) += board-kafa.o obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o obj-$(CONFIG_MACH_ECBAT91) += board-ecbat91.o obj-$(CONFIG_MACH_YL9200) += board-yl-9200.o +obj-$(CONFIG_MACH_CPUAT91) += board-cpuat91.o # AT91SAM9260 board-specific support obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c new file mode 100644 index 0000000000000..a28d99656190e --- /dev/null +++ b/arch/arm/mach-at91/board-cpuat91.c @@ -0,0 +1,185 @@ +/* + * linux/arch/arm/mach-at91/board-cpuat91.c + * + * Copyright (C) 2009 Eric Benard - eric@eukrea.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/plat-ram.h> + +#include <mach/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91rm9200_mc.h> + +#include "generic.h" + +static struct gpio_led cpuat91_leds[] = { + { + .name = "led1", + .default_trigger = "heartbeat", + .active_low = 1, + .gpio = AT91_PIN_PC0, + }, +}; + +static void __init cpuat91_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91rm9200_initialize(18432000, AT91RM9200_PQFP); + + /* DBGU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */ + at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | + ATMEL_UART_RTS); + + /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | + ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR | + ATMEL_UART_DCD | ATMEL_UART_RI); + + /* USART2 on ttyS3 (Rx, Tx) */ + at91_register_uart(AT91RM9200_ID_US2, 3, 0); + + /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */ + at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS | + ATMEL_UART_RTS); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init cpuat91_init_irq(void) +{ + at91rm9200_init_interrupts(NULL); +} + +static struct at91_eth_data __initdata cpuat91_eth_data = { + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata cpuat91_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata cpuat91_udc_data = { + .vbus_pin = AT91_PIN_PC15, + .pullup_pin = AT91_PIN_PC14, +}; + +static struct at91_mmc_data __initdata cpuat91_mmc_data = { + .det_pin = AT91_PIN_PC2, + .wire4 = 1, +}; + +static struct physmap_flash_data cpuat91_flash_data = { + .width = 2, +}; + +static struct resource cpuat91_flash_resource = { + .start = AT91_CHIPSELECT_0, + .end = AT91_CHIPSELECT_0 + SZ_16M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device cpuat91_norflash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &cpuat91_flash_data, + }, + .resource = &cpuat91_flash_resource, + .num_resources = 1, +}; + +#ifdef CONFIG_MTD_PLATRAM +struct platdata_mtd_ram at91_sram_pdata = { + .mapname = "SRAM", + .bankwidth = 2, +}; + +static struct resource at91_sram_resource[] = { + [0] = { + .start = AT91RM9200_SRAM_BASE, + .end = AT91RM9200_SRAM_BASE + AT91RM9200_SRAM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device at91_sram = { + .name = "mtd-ram", + .id = 0, + .resource = at91_sram_resource, + .num_resources = ARRAY_SIZE(at91_sram_resource), + .dev = { + .platform_data = &at91_sram_pdata, + }, +}; +#endif /* MTD_PLATRAM */ + +static struct platform_device *platform_devices[] __initdata = { + &cpuat91_norflash, +#ifdef CONFIG_MTD_PLATRAM + &at91_sram, +#endif /* CONFIG_MTD_PLATRAM */ +}; + +static void __init cpuat91_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* LEDs. */ + at91_gpio_leds(cpuat91_leds, ARRAY_SIZE(cpuat91_leds)); + /* Ethernet */ + at91_add_device_eth(&cpuat91_eth_data); + /* USB Host */ + at91_add_device_usbh(&cpuat91_usbh_data); + /* USB Device */ + at91_add_device_udc(&cpuat91_udc_data); + /* MMC */ + at91_add_device_mmc(0, &cpuat91_mmc_data); + /* I2C */ + at91_add_device_i2c(NULL, 0); + /* Platform devices */ + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); +} + +MACHINE_START(CPUAT91, "Eukrea") + /* Maintainer: Eric Benard - EUKREA Electromatique */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = cpuat91_map_io, + .init_irq = cpuat91_init_irq, + .init_machine = cpuat91_board_init, +MACHINE_END -- GitLab From 897bd6a363770ced6b78f6ae8882325c7590ed8b Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 31 Jul 2009 02:29:45 +0100 Subject: [PATCH 0963/1002] ARM: 5633/1: Add wdt resource for w90p910 platform Add wdt resource for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mach-w90p910evb.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c index 3e3a267b2dde5..117578aed6812 100644 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ b/arch/arm/mach-w90x900/mach-w90p910evb.c @@ -340,6 +340,28 @@ static struct spi_board_info w90p910_spi_board_info[] __initdata = { }, }; +/* WDT Device */ + +static struct resource w90p910_wdt_resource[] = { + [0] = { + .start = W90X900_PA_TIMER, + .end = W90X900_PA_TIMER + W90X900_SZ_TIMER - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_WDT, + .end = IRQ_WDT, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device w90p910_device_wdt = { + .name = "w90p910-wdt", + .id = -1, + .num_resources = ARRAY_SIZE(w90p910_wdt_resource), + .resource = w90p910_wdt_resource, +}; + static struct map_desc w90p910_iodesc[] __initdata = { }; @@ -357,6 +379,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = { &w90p910_device_fmi, &w90p910_device_emc, &w90p910_device_spi, + &w90p910_device_wdt, }; static void __init w90p910evb_map_io(void) -- GitLab From ae45b1c618d9e645a5e1decff31b710f739745fa Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 31 Jul 2009 02:30:32 +0100 Subject: [PATCH 0964/1002] ARM: 5634/1: Add static setting cpu frequence for w90p910 platform Add static setting cpu frequence for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/Makefile | 2 +- arch/arm/mach-w90x900/clksel.c | 91 +++++++++++++++++++ arch/arm/mach-w90x900/cpu.h | 1 + .../mach-w90x900/include/mach/regs-clock.h | 22 +++++ arch/arm/mach-w90x900/include/mach/regs-ebi.h | 33 +++++++ arch/arm/mach-w90x900/w90p910.c | 80 ++++++++++++++++ 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-w90x900/clksel.c create mode 100644 arch/arm/mach-w90x900/include/mach/regs-ebi.h diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile index d50c94f4dbdfd..3ccd625455cf8 100644 --- a/arch/arm/mach-w90x900/Makefile +++ b/arch/arm/mach-w90x900/Makefile @@ -5,7 +5,7 @@ # Object file lists. obj-y := irq.o time.o mfp-w90p910.o gpio.o clock.o - +obj-y += clksel.o # W90X900 CPU support files obj-$(CONFIG_CPU_W90P910) += w90p910.o diff --git a/arch/arm/mach-w90x900/clksel.c b/arch/arm/mach-w90x900/clksel.c new file mode 100644 index 0000000000000..5a77eb91cb16b --- /dev/null +++ b/arch/arm/mach-w90x900/clksel.c @@ -0,0 +1,91 @@ +/* + * linux/arch/arm/mach-w90x900/clksel.c + * + * Copyright (c) 2008 Nuvoton technology corporation + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/clk.h> +#include <linux/mutex.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/regs-clock.h> + +#define PLL0 0x00 +#define PLL1 0x01 +#define OTHER 0x02 +#define EXT 0x03 +#define MSOFFSET 0x0C +#define ATAOFFSET 0x0a +#define LCDOFFSET 0x06 +#define AUDOFFSET 0x04 +#define CPUOFFSET 0x00 + +static DEFINE_MUTEX(clksel_sem); + +static void clock_source_select(const char *dev_id, unsigned int clkval) +{ + unsigned int clksel, offset; + + clksel = __raw_readl(REG_CLKSEL); + + if (strcmp(dev_id, "w90p910-ms") == 0) + offset = MSOFFSET; + else if (strcmp(dev_id, "w90p910-atapi") == 0) + offset = ATAOFFSET; + else if (strcmp(dev_id, "w90p910-lcd") == 0) + offset = LCDOFFSET; + else if (strcmp(dev_id, "w90p910-audio") == 0) + offset = AUDOFFSET; + else + offset = CPUOFFSET; + + clksel &= ~(0x03 << offset); + clksel |= (clkval << offset); + + __raw_writel(clksel, REG_CLKSEL); +} + +void w90p910_clock_source(struct device *dev, unsigned char *src) +{ + unsigned int clkval; + const char *dev_id; + + BUG_ON(!src); + clkval = 0; + + mutex_lock(&clksel_sem); + + if (dev) + dev_id = dev_name(dev); + else + dev_id = "cpufreq"; + + if (strcmp(src, "pll0") == 0) + clkval = PLL0; + else if (strcmp(src, "pll1") == 0) + clkval = PLL1; + else if (strcmp(src, "ext") == 0) + clkval = EXT; + else if (strcmp(src, "oth") == 0) + clkval = OTHER; + + clock_source_select(dev_id, clkval); + + mutex_unlock(&clksel_sem); +} +EXPORT_SYMBOL(w90p910_clock_source); + diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h index 57b5dbabeb41a..ddde959d89870 100644 --- a/arch/arm/mach-w90x900/cpu.h +++ b/arch/arm/mach-w90x900/cpu.h @@ -45,6 +45,7 @@ extern void w90p910_init_clocks(void); extern void w90p910_map_io(struct map_desc *mach_desc, int size); extern struct platform_device w90p910_serial_device; extern struct sys_timer w90x900_timer; +extern void w90p910_clock_source(struct device *dev, unsigned char *src); #define W90X900_8250PORT(name) \ { \ diff --git a/arch/arm/mach-w90x900/include/mach/regs-clock.h b/arch/arm/mach-w90x900/include/mach/regs-clock.h index f10b6a8dc069a..516d6b477b614 100644 --- a/arch/arm/mach-w90x900/include/mach/regs-clock.h +++ b/arch/arm/mach-w90x900/include/mach/regs-clock.h @@ -28,4 +28,26 @@ #define REG_CLKEN1 (CLK_BA + 0x24) #define REG_CLKDIV1 (CLK_BA + 0x28) +/* Define PLL freq setting */ +#define PLL_DISABLE 0x12B63 +#define PLL_66MHZ 0x2B63 +#define PLL_100MHZ 0x4F64 +#define PLL_120MHZ 0x4F63 +#define PLL_166MHZ 0x4124 +#define PLL_200MHZ 0x4F24 + +/* Define AHB:CPUFREQ ratio */ +#define AHB_CPUCLK_1_1 0x00 +#define AHB_CPUCLK_1_2 0x01 +#define AHB_CPUCLK_1_4 0x02 +#define AHB_CPUCLK_1_8 0x03 + +/* Define APB:AHB ratio */ +#define APB_AHB_1_2 0x01 +#define APB_AHB_1_4 0x02 +#define APB_AHB_1_8 0x03 + +/* Define clock skew */ +#define DEFAULTSKEW 0x48 + #endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-w90x900/include/mach/regs-ebi.h b/arch/arm/mach-w90x900/include/mach/regs-ebi.h new file mode 100644 index 0000000000000..b68455e7f88b7 --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/regs-ebi.h @@ -0,0 +1,33 @@ +/* + * arch/arm/mach-w90x900/include/mach/regs-ebi.h + * + * Copyright (c) 2009 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#ifndef __ASM_ARCH_REGS_EBI_H +#define __ASM_ARCH_REGS_EBI_H + +/* EBI Control Registers */ + +#define EBI_BA W90X900_VA_EBI +#define REG_EBICON (EBI_BA + 0x00) +#define REG_ROMCON (EBI_BA + 0x04) +#define REG_SDCONF0 (EBI_BA + 0x08) +#define REG_SDCONF1 (EBI_BA + 0x0C) +#define REG_SDTIME0 (EBI_BA + 0x10) +#define REG_SDTIME1 (EBI_BA + 0x14) +#define REG_EXT0CON (EBI_BA + 0x18) +#define REG_EXT1CON (EBI_BA + 0x1C) +#define REG_EXT2CON (EBI_BA + 0x20) +#define REG_EXT3CON (EBI_BA + 0x24) +#define REG_EXT4CON (EBI_BA + 0x28) +#define REG_CKSKEW (EBI_BA + 0x2C) + +#endif /* __ASM_ARCH_REGS_EBI_H */ diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index 6ebf5cfc78daa..8444eababaab3 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/serial_8250.h> +#include <linux/delay.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -32,6 +33,8 @@ #include <mach/hardware.h> #include <mach/regs-serial.h> +#include <mach/regs-clock.h> +#include <mach/regs-ebi.h> #include "cpu.h" #include "clock.h" @@ -123,6 +126,83 @@ void __init w90p910_map_io(struct map_desc *mach_desc, int mach_size) printk(KERN_ERR "CPU type 0x%08lx is not W90P910\n", idcode); } +/*Set W90P910 cpu frequence*/ +static int __init w90p910_set_clkval(unsigned int cpufreq) +{ + unsigned int pllclk, ahbclk, apbclk, val; + + pllclk = 0; + ahbclk = 0; + apbclk = 0; + + switch (cpufreq) { + case 66: + pllclk = PLL_66MHZ; + ahbclk = AHB_CPUCLK_1_1; + apbclk = APB_AHB_1_2; + break; + + case 100: + pllclk = PLL_100MHZ; + ahbclk = AHB_CPUCLK_1_1; + apbclk = APB_AHB_1_2; + break; + + case 120: + pllclk = PLL_120MHZ; + ahbclk = AHB_CPUCLK_1_2; + apbclk = APB_AHB_1_2; + break; + + case 166: + pllclk = PLL_166MHZ; + ahbclk = AHB_CPUCLK_1_2; + apbclk = APB_AHB_1_2; + break; + + case 200: + pllclk = PLL_200MHZ; + ahbclk = AHB_CPUCLK_1_2; + apbclk = APB_AHB_1_2; + break; + } + + __raw_writel(pllclk, REG_PLLCON0); + + val = __raw_readl(REG_CLKDIV); + val &= ~(0x03 << 24 | 0x03 << 26); + val |= (ahbclk << 24 | apbclk << 26); + __raw_writel(val, REG_CLKDIV); + + return 0; +} +static int __init w90p910_set_cpufreq(char *str) +{ + unsigned long cpufreq, val; + + if (!*str) + return 0; + + strict_strtoul(str, 0, &cpufreq); + + w90p910_clock_source(NULL, "ext"); + + w90p910_set_clkval(cpufreq); + + mdelay(1); + + val = __raw_readl(REG_CKSKEW); + val &= ~0xff; + val |= DEFAULTSKEW; + __raw_writel(val, REG_CKSKEW); + + w90p910_clock_source(NULL, "pll0"); + + return 1; +} + +__setup("cpufreq=", w90p910_set_cpufreq); + /*Init W90P910 clock*/ void __init w90p910_init_clocks(void) -- GitLab From fb85205ada3fef98122a40b700ecb71efb33ae71 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich <geomatsi@gmail.com> Date: Thu, 30 Jul 2009 22:23:24 +0100 Subject: [PATCH 0965/1002] ARM: 5631/1: Platform data for CF/IDE support in AT91SAM9260 This patch adds platform data for CF/IDE support and SMC init code for AT91SAM9260 SoC. Tested-by: Sergey Matyukevich <geomatsi@gmail.com> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/at91sam9260_devices.c | 116 +++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index d74c9ac007e75..ee4ea0e720cf1 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -1113,6 +1113,122 @@ void __init at91_set_serial_console(unsigned portnr) {} void __init at91_add_device_serial(void) {} #endif +/* -------------------------------------------------------------------- + * CF/IDE + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) || \ + defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \ + defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) + +static struct at91_cf_data cf0_data; + +static struct resource cf0_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_4, + .end = AT91_CHIPSELECT_4 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device cf0_device = { + .id = 0, + .dev = { + .platform_data = &cf0_data, + }, + .resource = cf0_resources, + .num_resources = ARRAY_SIZE(cf0_resources), +}; + +static struct at91_cf_data cf1_data; + +static struct resource cf1_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_5, + .end = AT91_CHIPSELECT_5 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device cf1_device = { + .id = 1, + .dev = { + .platform_data = &cf1_data, + }, + .resource = cf1_resources, + .num_resources = ARRAY_SIZE(cf1_resources), +}; + +void __init at91_add_device_cf(struct at91_cf_data *data) +{ + struct platform_device *pdev; + unsigned long csa; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + + switch (data->chipselect) { + case 4: + at91_set_multi_drive(AT91_PIN_PC8, 0); + at91_set_A_periph(AT91_PIN_PC8, 0); + csa |= AT91_MATRIX_CS4A_SMC_CF1; + cf0_data = *data; + pdev = &cf0_device; + break; + case 5: + at91_set_multi_drive(AT91_PIN_PC9, 0); + at91_set_A_periph(AT91_PIN_PC9, 0); + csa |= AT91_MATRIX_CS5A_SMC_CF2; + cf1_data = *data; + pdev = &cf1_device; + break; + default: + printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n", + data->chipselect); + return; + } + + at91_sys_write(AT91_MATRIX_EBICSA, csa); + + if (data->rst_pin) { + at91_set_multi_drive(data->rst_pin, 0); + at91_set_gpio_output(data->rst_pin, 1); + } + + if (data->irq_pin) { + at91_set_gpio_input(data->irq_pin, 0); + at91_set_deglitch(data->irq_pin, 1); + } + + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 0); + at91_set_deglitch(data->det_pin, 1); + } + + at91_set_B_periph(AT91_PIN_PC6, 0); /* CFCE1 */ + at91_set_B_periph(AT91_PIN_PC7, 0); /* CFCE2 */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* CFRNW */ + at91_set_A_periph(AT91_PIN_PC15, 1); /* NWAIT */ + + if (data->flags & AT91_CF_TRUE_IDE) +#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) + pdev->name = "pata_at91"; +#elif defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) + pdev->name = "at91_ide"; +#else +#warning "board requires AT91_CF_TRUE_IDE: enable either at91_ide or pata_at91" +#endif + else + pdev->name = "at91_cf"; + + platform_device_register(pdev); +} + +#else +void __init at91_add_device_cf(struct at91_cf_data * data) {} +#endif /* -------------------------------------------------------------------- */ /* -- GitLab From 0c30df6fe0bd1e3845357e793dc1bfd908751c45 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich <geomatsi@gmail.com> Date: Thu, 30 Jul 2009 22:29:07 +0100 Subject: [PATCH 0966/1002] ARM: 5632/1: Board-specific data for IDE support on afeb9260 This patch adds board-specific data for IDE support on afeb9260. Depends on #5631/1 Tested-by: Sergey Matyukevich <geomatsi@gmail.com> Signed-off-by: Sergey Matyukevich <geomatsi@gmail.com> Acked-by: Andrew Victor <linux@maxim.org.za> Acked-by: Sergey Lapin <slapin@ossfans.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-afeb-9260v1.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c index 970fd6b6753ea..61e52b66bc72e 100644 --- a/arch/arm/mach-at91/board-afeb-9260v1.c +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -174,6 +174,16 @@ static struct i2c_board_info __initdata afeb9260_i2c_devices[] = { }, }; +/* + * IDE (CF True IDE mode) + */ +static struct at91_cf_data afeb9260_cf_data = { + .chipselect = 4, + .irq_pin = AT91_PIN_PA6, + .rst_pin = AT91_PIN_PA7, + .flags = AT91_CF_TRUE_IDE, +}; + static void __init afeb9260_board_init(void) { /* Serial */ @@ -202,6 +212,8 @@ static void __init afeb9260_board_init(void) ARRAY_SIZE(afeb9260_i2c_devices)); /* Audio */ at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX); + /* IDE */ + at91_add_device_cf(&afeb9260_cf_data); } MACHINE_START(AFEB9260, "Custom afeb9260 board") -- GitLab From a084fcfae541abc0eeecdd73ceeb01fb2453df4e Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sat, 1 Aug 2009 16:26:03 +0100 Subject: [PATCH 0967/1002] [ARM] Update mach-types Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/tools/mach-types | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 30af432946935..200d83a98286a 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Thu Jul 9 20:56:13 2009 +# Last update: Sat Aug 1 16:26:02 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -2313,3 +2313,39 @@ openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325 incredible MACH_INCREDIBLE INCREDIBLE 2326 incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327 heroct MACH_HEROCT HEROCT 2328 +mmnet1000 MACH_MMNET1000 MMNET1000 2329 +devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330 +devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331 +mx31txtr MACH_MX31TXTR MX31TXTR 2332 +u380 MACH_U380 U380 2333 +oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334 +npcmx50 MACH_NPCMX50 NPCMX50 2335 +mx51_lange51 MACH_MX51_LANGE51 MX51_LANGE51 2336 +mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337 +riom MACH_RIOM RIOM 2338 +comcas MACH_COMCAS COMCAS 2339 +wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340 +cm_t35 MACH_CM_T35 CM_T35 2341 +net2big MACH_NET2BIG NET2BIG 2342 +motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343 +igep0020 MACH_IGEP0020 IGEP0020 2344 +igep0010 MACH_IGEP0010 IGEP0010 2345 +mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346 +scat100 MACH_SCAT100 SCAT100 2347 +sanmina MACH_SANMINA SANMINA 2348 +momento MACH_MOMENTO MOMENTO 2349 +nuc9xx MACH_NUC9XX NUC9XX 2350 +nuc910evb MACH_NUC910EVB NUC910EVB 2351 +nuc920evb MACH_NUC920EVB NUC920EVB 2352 +nuc950evb MACH_NUC950EVB NUC950EVB 2353 +nuc945evb MACH_NUC945EVB NUC945EVB 2354 +nuc960evb MACH_NUC960EVB NUC960EVB 2355 +nuc932evb MACH_NUC932EVB NUC932EVB 2356 +nuc900 MACH_NUC900 NUC900 2357 +sd1soc MACH_SD1SOC SD1SOC 2358 +ln2440bc MACH_LN2440BC LN2440BC 2359 +rsbc MACH_RSBC RSBC 2360 +openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 +hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 +wayland MACH_WAYLAND WAYLAND 2363 +acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 -- GitLab From af1057abd7d5f97e17ab96e34d1920746188ddcb Mon Sep 17 00:00:00 2001 From: Julia Lawall <julia@diku.dk> Date: Mon, 3 Aug 2009 11:57:20 +0100 Subject: [PATCH 0968/1002] ARM: 5635/1: Use DIV_ROUND_CLOSEST The kernel.h macro DIV_ROUND_CLOSEST performs the computation (x + d/2)/d but is perhaps more readable. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // <smpl> @haskernel@ @@ @depends on haskernel@ expression x,__divisor; @@ - (((x) + ((__divisor) / 2)) / (__divisor)) + DIV_ROUND_CLOSEST(x,__divisor) // </smpl> Signed-off-by: Julia Lawall <julia@diku.dk> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-ep93xx/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 40755298fa330..16b92c37ec99a 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -82,7 +82,7 @@ void __init ep93xx_map_io(void) */ static unsigned int last_jiffy_time; -#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) +#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ) static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) { -- GitLab From 369842658a36bcea28ecb643ba4bdb53919330dd Mon Sep 17 00:00:00 2001 From: Mikael Pettersson <mikpe@it.uu.se> Date: Sat, 15 Aug 2009 12:58:11 +0100 Subject: [PATCH 0969/1002] ARM: 5677/1: ARM support for TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait This patch adds support for TIF_RESTORE_SIGMASK to ARM's signal handling, which allows to hook up the pselect6, ppoll, and epoll_pwait syscalls on ARM. Tested here with eabi userspace and a test program with a deliberate race between a child's exit and the parent's sigprocmask/select sequence. Using sys_pselect6() instead of sigprocmask/select reliably prevents the race. The other arch's support for TIF_RESTORE_SIGMASK has evolved over time: In 2.6.16: - add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING - test both when checking for pending signal [changed later] - reimplement sys_sigsuspend() to use current->saved_sigmask, TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND; ditto for sys_rt_sigsuspend(), but drop private code and use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND; - there are now no "extra" calls to do_signal() so its oldset parameter is always ¤t->blocked so need not be passed, also its return value is changed to void - change handle_signal() to return 0/-errno - change do_signal() to honor TIF_RESTORE_SIGMASK: + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK + if no signal was delivered and TIF_RESTORE_SIGMASK is set then clear it and restore the sigmask - hook up sys_pselect6() and sys_ppoll() In 2.6.19: - hook up sys_epoll_pwait() In 2.6.26: - allow archs to override how TIF_RESTORE_SIGMASK is implemented; default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again when checking for pending signal work; some archs now implement TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit - call set_restore_sigmask() in sys_sigsuspend() instead of setting TIF_RESTORE_SIGMASK In 2.6.29-rc: - kill sys_pselect7() which no arch wanted So for 2.6.31-rc6/ARM this patch does the following: - Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask() which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so TIF_RESTORE_SIGMASK need not claim one of the scarce low thread flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need not be extended for TIF_RESTORE_SIGMASK. - sys_sigsuspend() is reimplemented to use current->saved_sigmask and set_restore_sigmask(), making it identical to most other archs - The private code for sys_rt_sigsuspend() is removed, instead generic code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND. - sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs parameter, so their assembly code wrappers are removed. - handle_signal() is changed to return 0 on success or -errno. - The oldset parameter to do_signal() is now redundant and removed, and the return value is now also redundant and changed to void. - do_signal() is changed to honor TIF_RESTORE_SIGMASK: + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK + if no signal was delivered and TIF_RESTORE_SIGMASK is set then clear it and restore the sigmask - Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait. Signed-off-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/include/asm/thread_info.h | 2 + arch/arm/include/asm/unistd.h | 7 +-- arch/arm/kernel/calls.S | 10 ++-- arch/arm/kernel/entry-common.S | 10 ---- arch/arm/kernel/signal.c | 86 +++++++++++++----------------- 5 files changed, 48 insertions(+), 67 deletions(-) diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 73394e50cbca2..e20d80539b42a 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -140,6 +140,7 @@ extern void vfp_sync_state(struct thread_info *thread); #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 #define TIF_FREEZE 19 +#define TIF_RESTORE_SIGMASK 20 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) @@ -147,6 +148,7 @@ extern void vfp_sync_state(struct thread_info *thread); #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) #define _TIF_FREEZE (1 << TIF_FREEZE) +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) /* * Change these and you break ASM code in entry-common.S diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 0e97b8cb77d50..9122c9ee18fb5 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -360,8 +360,8 @@ #define __NR_readlinkat (__NR_SYSCALL_BASE+332) #define __NR_fchmodat (__NR_SYSCALL_BASE+333) #define __NR_faccessat (__NR_SYSCALL_BASE+334) - /* 335 for pselect6 */ - /* 336 for ppoll */ +#define __NR_pselect6 (__NR_SYSCALL_BASE+335) +#define __NR_ppoll (__NR_SYSCALL_BASE+336) #define __NR_unshare (__NR_SYSCALL_BASE+337) #define __NR_set_robust_list (__NR_SYSCALL_BASE+338) #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) @@ -372,7 +372,7 @@ #define __NR_vmsplice (__NR_SYSCALL_BASE+343) #define __NR_move_pages (__NR_SYSCALL_BASE+344) #define __NR_getcpu (__NR_SYSCALL_BASE+345) - /* 346 for epoll_pwait */ +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) #define __NR_kexec_load (__NR_SYSCALL_BASE+347) #define __NR_utimensat (__NR_SYSCALL_BASE+348) #define __NR_signalfd (__NR_SYSCALL_BASE+349) @@ -432,6 +432,7 @@ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) #define __ARCH_WANT_SYS_TIME diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index f776e72a4cb82..ecfa98954d1d9 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -81,7 +81,7 @@ CALL(sys_ni_syscall) /* was sys_ssetmask */ /* 70 */ CALL(sys_setreuid16) CALL(sys_setregid16) - CALL(sys_sigsuspend_wrapper) + CALL(sys_sigsuspend) CALL(sys_sigpending) CALL(sys_sethostname) /* 75 */ CALL(sys_setrlimit) @@ -188,7 +188,7 @@ CALL(sys_rt_sigpending) CALL(sys_rt_sigtimedwait) CALL(sys_rt_sigqueueinfo) - CALL(sys_rt_sigsuspend_wrapper) + CALL(sys_rt_sigsuspend) /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) CALL(sys_chown16) @@ -344,8 +344,8 @@ CALL(sys_readlinkat) CALL(sys_fchmodat) CALL(sys_faccessat) -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */ - CALL(sys_ni_syscall) /* eventually ppoll */ +/* 335 */ CALL(sys_pselect6) + CALL(sys_ppoll) CALL(sys_unshare) CALL(sys_set_robust_list) CALL(sys_get_robust_list) @@ -355,7 +355,7 @@ CALL(sys_vmsplice) CALL(sys_move_pages) /* 345 */ CALL(sys_getcpu) - CALL(sys_ni_syscall) /* eventually epoll_pwait */ + CALL(sys_epoll_pwait) CALL(sys_kexec_load) CALL(sys_utimensat) CALL(sys_signalfd) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 366e5097a41a4..bfa7f0af7ede5 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -373,16 +373,6 @@ sys_clone_wrapper: b sys_clone ENDPROC(sys_clone_wrapper) -sys_sigsuspend_wrapper: - add r3, sp, #S_OFF - b sys_sigsuspend -ENDPROC(sys_sigsuspend_wrapper) - -sys_rt_sigsuspend_wrapper: - add r2, sp, #S_OFF - b sys_rt_sigsuspend -ENDPROC(sys_rt_sigsuspend_wrapper) - sys_sigreturn_wrapper: add r0, sp, #S_OFF b sys_sigreturn diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 93bb4247b7ed0..e27ee1f701d5c 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -47,57 +47,22 @@ const unsigned long sigreturn_codes[7] = { MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, }; -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); - /* * atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->ARM_r0 = -EINTR; - - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs, 0)) - return regs->ARM_r0; - } -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->ARM_r0 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs, 0)) - return regs->ARM_r0; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_restore_sigmask(); + return -ERESTARTNOHAND; } asmlinkage int @@ -545,7 +510,7 @@ static inline void setup_syscall_restart(struct pt_regs *regs) /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, int syscall) @@ -596,7 +561,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, if (ret != 0) { force_sigsegv(sig, tsk); - return; + return ret; } /* @@ -610,6 +575,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, recalc_sigpending(); spin_unlock_irq(&tsk->sighand->siglock); + return 0; } /* @@ -621,7 +587,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) +static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; @@ -634,7 +600,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) * if so. */ if (!user_mode(regs)) - return 0; + return; if (try_to_freeze()) goto no_signal; @@ -643,9 +609,24 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &ka, &info, oldset, regs, syscall); + sigset_t *oldset; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } single_step_set(current); - return 1; + return; } no_signal: @@ -697,14 +678,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) regs->ARM_r0 == -ERESTARTNOINTR) { setup_syscall_restart(regs); } + + /* If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } single_step_set(current); - return 0; } asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) { if (thread_flags & _TIF_SIGPENDING) - do_signal(¤t->blocked, regs, syscall); + do_signal(regs, syscall); } -- GitLab From 58b5369e6eb6c889b540a99aa95562a66b25acf1 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 14 Aug 2009 15:36:44 +0100 Subject: [PATCH 0970/1002] ARM: 5674/1: Add clocksource/clockevent support for w90p910 platform Add clocksource/clockevent support for w90p910 platform. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/Kconfig | 2 + arch/arm/mach-w90x900/clock.c | 6 ++ arch/arm/mach-w90x900/time.c | 151 +++++++++++++++++++++++++++----- arch/arm/mach-w90x900/w90p910.c | 2 + 4 files changed, 137 insertions(+), 24 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c3fed1ee7304c..8c4f03d34124a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -495,6 +495,8 @@ config ARCH_W90X900 select GENERIC_GPIO select HAVE_CLK select COMMON_CLKDEV + select GENERIC_TIME + select GENERIC_CLOCKEVENTS help Support for Nuvoton (Winbond logic dept.) ARM9 processor,You can login www.mcuos.com or www.nuvoton.com to know more. diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c index 49cf1fbc14eb4..70b671096377f 100644 --- a/arch/arm/mach-w90x900/clock.c +++ b/arch/arm/mach-w90x900/clock.c @@ -55,6 +55,12 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); +unsigned long clk_get_rate(struct clk *clk) +{ + return 15000000; +} +EXPORT_SYMBOL(clk_get_rate); + void w90x900_clk_enable(struct clk *clk, int enable) { unsigned int clocks = clk->cken; diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index bcc838f6b3936..5e06770e60143 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -3,7 +3,7 @@ * * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks * - * Copyright (c) 2008 Nuvoton technology corporation + * Copyright (c) 2009 Nuvoton technology corporation * All rights reserved. * * Wan ZongShun <mcuos.com@gmail.com> @@ -23,6 +23,8 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/leds.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> #include <asm/mach-types.h> #include <asm/mach/irq.h> @@ -31,49 +33,150 @@ #include <mach/map.h> #include <mach/regs-timer.h> -static unsigned long w90x900_gettimeoffset(void) +#define RESETINT 0x1f +#define PERIOD (0x01 << 27) +#define ONESHOT (0x00 << 27) +#define COUNTEN (0x01 << 30) +#define INTEN (0x01 << 29) + +#define TICKS_PER_SEC 100 +#define PRESCALE 0x63 /* Divider = prescale + 1 */ + +unsigned int timer0_load; + +static void w90p910_clockevent_setmode(enum clock_event_mode mode, + struct clock_event_device *clk) { + unsigned int val; + + val = __raw_readl(REG_TCSR0); + val &= ~(0x03 << 27); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writel(timer0_load, REG_TICR0); + val |= (PERIOD | COUNTEN | INTEN | PRESCALE); + break; + + case CLOCK_EVT_MODE_ONESHOT: + val |= (ONESHOT | COUNTEN | INTEN | PRESCALE); + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + } + + __raw_writel(val, REG_TCSR0); +} + +static int w90p910_clockevent_setnextevent(unsigned long evt, + struct clock_event_device *clk) +{ + unsigned int val; + + __raw_writel(evt, REG_TICR0); + + val = __raw_readl(REG_TCSR0); + val |= (COUNTEN | INTEN | PRESCALE); + __raw_writel(val, REG_TCSR0); + return 0; } +static struct clock_event_device w90p910_clockevent_device = { + .name = "w90p910-timer0", + .shift = 32, + .features = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = w90p910_clockevent_setmode, + .set_next_event = w90p910_clockevent_setnextevent, + .rating = 300, +}; + /*IRQ handler for the timer*/ -static irqreturn_t -w90x900_timer_interrupt(int irq, void *dev_id) +static irqreturn_t w90p910_timer0_interrupt(int irq, void *dev_id) { - timer_tick(); + struct clock_event_device *evt = &w90p910_clockevent_device; + __raw_writel(0x01, REG_TISR); /* clear TIF0 */ + + evt->event_handler(evt); return IRQ_HANDLED; } -static struct irqaction w90x900_timer_irq = { - .name = "w90x900 Timer Tick", +static struct irqaction w90p910_timer0_irq = { + .name = "w90p910-timer0", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = w90x900_timer_interrupt, + .handler = w90p910_timer0_interrupt, }; -/*Set up timer reg.*/ +static void __init w90p910_clockevents_init(unsigned int rate) +{ + w90p910_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, + w90p910_clockevent_device.shift); + w90p910_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, + &w90p910_clockevent_device); + w90p910_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, + &w90p910_clockevent_device); + w90p910_clockevent_device.cpumask = cpumask_of(0); -static void w90x900_timer_setup(void) + clockevents_register_device(&w90p910_clockevent_device); +} + +static cycle_t w90p910_get_cycles(struct clocksource *cs) { - __raw_writel(0, REG_TCSR0); - __raw_writel(0, REG_TCSR1); - __raw_writel(0, REG_TCSR2); - __raw_writel(0, REG_TCSR3); - __raw_writel(0, REG_TCSR4); - __raw_writel(0x1F, REG_TISR); - __raw_writel(15000000/(100 * 100), REG_TICR0); - __raw_writel(0x68000063, REG_TCSR0); + return ~__raw_readl(REG_TDR1); } -static void __init w90x900_timer_init(void) +static struct clocksource clocksource_w90p910 = { + .name = "w90p910-timer1", + .rating = 200, + .read = w90p910_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init w90p910_clocksource_init(unsigned int rate) { - w90x900_timer_setup(); - setup_irq(IRQ_TIMER0, &w90x900_timer_irq); + unsigned int val; + + __raw_writel(0xffffffff, REG_TICR1); + + val = __raw_readl(REG_TCSR1); + val |= (COUNTEN | PERIOD); + __raw_writel(val, REG_TCSR1); + + clocksource_w90p910.mult = + clocksource_khz2mult((rate / 1000), clocksource_w90p910.shift); + clocksource_register(&clocksource_w90p910); +} + +static void __init w90p910_timer_init(void) +{ + struct clk *ck_ext = clk_get(NULL, "ext"); + unsigned int rate; + + BUG_ON(IS_ERR(ck_ext)); + + rate = clk_get_rate(ck_ext); + clk_put(ck_ext); + rate = rate / (PRESCALE + 0x01); + + /* set a known state */ + __raw_writel(0x00, REG_TCSR0); + __raw_writel(0x00, REG_TCSR1); + __raw_writel(RESETINT, REG_TISR); + timer0_load = (rate / TICKS_PER_SEC); + + setup_irq(IRQ_TIMER0, &w90p910_timer0_irq); + + w90p910_clocksource_init(rate); + w90p910_clockevents_init(rate); } struct sys_timer w90x900_timer = { - .init = w90x900_timer_init, - .offset = w90x900_gettimeoffset, - .resume = w90x900_timer_setup + .init = w90p910_timer_init, }; diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index 8444eababaab3..d33723b69d148 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c @@ -76,6 +76,7 @@ static DEFINE_CLK(wdt, 26); static DEFINE_CLK(gdma, 27); static DEFINE_CLK(adc, 28); static DEFINE_CLK(usi, 29); +static DEFINE_CLK(ext, 0); static struct clk_lookup w90p910_clkregs[] = { DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), @@ -97,6 +98,7 @@ static struct clk_lookup w90p910_clkregs[] = { DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), + DEF_CLKLOOK(&clk_ext, NULL, "ext"), }; /* Initial serial platform data */ -- GitLab From f346becf2fdba4d9dc023d28bc9a28f74dc9e4ac Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 14 Aug 2009 15:37:42 +0100 Subject: [PATCH 0971/1002] ARM: 5675/1: The semaphore is used as mutex so make it a mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The semaphore is used as mutex so make it a mutex. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/mfp-w90p910.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-w90x900/mfp-w90p910.c b/arch/arm/mach-w90x900/mfp-w90p910.c index e11a32b6856d7..4533098a0ee48 100644 --- a/arch/arm/mach-w90x900/mfp-w90p910.c +++ b/arch/arm/mach-w90x900/mfp-w90p910.c @@ -40,7 +40,7 @@ #define ENI2C0 (0x01 << 14) #define ENI2C1 (0x01 << 16) -static DECLARE_MUTEX(mfp_sem); +static DEFINE_MUTEX(mfp_mutex); void mfp_set_groupf(struct device *dev) { @@ -49,7 +49,7 @@ void mfp_set_groupf(struct device *dev) BUG_ON(!dev); - down(&mfp_sem); + mutex_lock(&mfp_mutex); dev_id = dev_name(dev); @@ -62,7 +62,7 @@ void mfp_set_groupf(struct device *dev) __raw_writel(mfpen, REG_MFSEL); - up(&mfp_sem); + mutex_unlock(&mfp_mutex); } EXPORT_SYMBOL(mfp_set_groupf); @@ -73,7 +73,7 @@ void mfp_set_groupc(struct device *dev) BUG_ON(!dev); - down(&mfp_sem); + mutex_lock(&mfp_mutex); dev_id = dev_name(dev); @@ -92,7 +92,7 @@ void mfp_set_groupc(struct device *dev) __raw_writel(mfpen, REG_MFSEL); - up(&mfp_sem); + mutex_unlock(&mfp_mutex); } EXPORT_SYMBOL(mfp_set_groupc); @@ -103,7 +103,7 @@ void mfp_set_groupi(struct device *dev) BUG_ON(!dev); - down(&mfp_sem); + mutex_lock(&mfp_mutex); dev_id = dev_name(dev); @@ -120,7 +120,7 @@ void mfp_set_groupi(struct device *dev) __raw_writel(mfpen, REG_MFSEL); - up(&mfp_sem); + mutex_unlock(&mfp_mutex); } EXPORT_SYMBOL(mfp_set_groupi); @@ -131,7 +131,7 @@ void mfp_set_groupg(struct device *dev) BUG_ON(!dev); - down(&mfp_sem); + mutex_lock(&mfp_mutex); dev_id = dev_name(dev); @@ -152,7 +152,7 @@ void mfp_set_groupg(struct device *dev) __raw_writel(mfpen, REG_MFSEL); - up(&mfp_sem); + mutex_unlock(&mfp_mutex); } EXPORT_SYMBOL(mfp_set_groupg); -- GitLab From a8bc4eadd936bbad9e99b89fe692679451ad75c9 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 14 Aug 2009 15:38:29 +0100 Subject: [PATCH 0972/1002] ARM: 5676/1: Provide more useful introduction for w90x900 Provide more useful introduction for w90x900 Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/Kconfig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8c4f03d34124a..aad0add99a5eb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -498,8 +498,13 @@ config ARCH_W90X900 select GENERIC_TIME select GENERIC_CLOCKEVENTS help - Support for Nuvoton (Winbond logic dept.) ARM9 processor,You - can login www.mcuos.com or www.nuvoton.com to know more. + Support for Nuvoton (Winbond logic dept.) ARM9 processor, + At present, the w90x900 has been renamed nuc900, regarding + the ARM series product line, you can login the following + link address to know more. + + <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ + ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller> config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" -- GitLab From 4663712cc745324a216112a72c744bb2b8f6658b Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:56:19 +0100 Subject: [PATCH 0973/1002] ARM: 5643/1: bcmring: arch.c and header files add arch.c in mach-bcmring add related header files in mach-bcmring Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/arch.c | 157 ++++++++++++++++++ arch/arm/mach-bcmring/core.h | 30 ++++ arch/arm/mach-bcmring/include/cfg_global.h | 13 ++ .../mach-bcmring/include/cfg_global_defines.h | 40 +++++ arch/arm/mach-bcmring/include/mach/hardware.h | 60 +++++++ arch/arm/mach-bcmring/include/mach/system.h | 54 ++++++ 6 files changed, 354 insertions(+) create mode 100644 arch/arm/mach-bcmring/arch.c create mode 100644 arch/arm/mach-bcmring/core.h create mode 100644 arch/arm/mach-bcmring/include/cfg_global.h create mode 100644 arch/arm/mach-bcmring/include/cfg_global_defines.h create mode 100644 arch/arm/mach-bcmring/include/mach/hardware.h create mode 100644 arch/arm/mach-bcmring/include/mach/system.h diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c new file mode 100644 index 0000000000000..0da693b0f7e16 --- /dev/null +++ b/arch/arm/mach-bcmring/arch.c @@ -0,0 +1,157 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/module.h> + +#include <linux/proc_fs.h> +#include <linux/sysctl.h> + +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/time.h> + +#include <asm/mach/arch.h> +#include <mach/dma.h> +#include <mach/hardware.h> +#include <mach/csp/mm_io.h> +#include <mach/csp/chipcHw_def.h> +#include <mach/csp/chipcHw_inline.h> + +#include <cfg_global.h> + +#include "core.h" + +HW_DECLARE_SPINLOCK(arch) +HW_DECLARE_SPINLOCK(gpio) +#if defined(CONFIG_DEBUG_SPINLOCK) + EXPORT_SYMBOL(bcmring_gpio_reg_lock); +#endif + +/* FIXME: temporary solution */ +#define BCM_SYSCTL_REBOOT_WARM 1 +#define CTL_BCM_REBOOT 112 + +/* sysctl */ +int bcmring_arch_warm_reboot; /* do a warm reboot on hard reset */ + +static struct ctl_table_header *bcmring_sysctl_header; + +static struct ctl_table bcmring_sysctl_warm_reboot[] = { + { + .ctl_name = BCM_SYSCTL_REBOOT_WARM, + .procname = "warm", + .data = &bcmring_arch_warm_reboot, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec}, + {} +}; + +static struct ctl_table bcmring_sysctl_reboot[] = { + { + .ctl_name = CTL_BCM_REBOOT, + .procname = "reboot", + .mode = 0555, + .child = bcmring_sysctl_warm_reboot}, + {} +}; + +static struct platform_device nand_device = { + .name = "bcm-nand", + .id = -1, +}; + +static struct platform_device *devices[] __initdata = { + &nand_device, +}; + +/**************************************************************************** +* +* Called from the customize_machine function in arch/arm/kernel/setup.c +* +* The customize_machine function is tagged as an arch_initcall +* (see include/linux/init.h for the order that the various init sections +* are called in. +* +*****************************************************************************/ +static void __init bcmring_init_machine(void) +{ + + bcmring_sysctl_header = register_sysctl_table(bcmring_sysctl_reboot); + + /* Enable spread spectrum */ + chipcHw_enableSpreadSpectrum(); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + bcmring_amba_init(); + + dma_init(); +} + +/**************************************************************************** +* +* Called from setup_arch (in arch/arm/kernel/setup.c) to fixup any tags +* passed in by the boot loader. +* +*****************************************************************************/ + +static void __init bcmring_fixup(struct machine_desc *desc, + struct tag *t, char **cmdline, struct meminfo *mi) { +#ifdef CONFIG_BLK_DEV_INITRD + printk(KERN_NOTICE "bcmring_fixup\n"); + t->hdr.tag = ATAG_CORE; + t->hdr.size = tag_size(tag_core); + t->u.core.flags = 0; + t->u.core.pagesize = PAGE_SIZE; + t->u.core.rootdev = 31 << 8 | 0; + t = tag_next(t); + + t->hdr.tag = ATAG_MEM; + t->hdr.size = tag_size(tag_mem32); + t->u.mem.start = CFG_GLOBAL_RAM_BASE; + t->u.mem.size = CFG_GLOBAL_RAM_SIZE; + + t = tag_next(t); + + t->hdr.tag = ATAG_NONE; + t->hdr.size = 0; +#endif +} + +/**************************************************************************** +* +* Machine Description +* +*****************************************************************************/ + +MACHINE_START(BCMRING, "BCMRING") + /* Maintainer: Broadcom Corporation */ + .phys_io = MM_IO_START, + .io_pg_offst = (MM_IO_BASE >> 18) & 0xfffc, + .fixup = bcmring_fixup, + .map_io = bcmring_map_io, + .init_irq = bcmring_init_irq, + .timer = &bcmring_timer, + .init_machine = bcmring_init_machine +MACHINE_END diff --git a/arch/arm/mach-bcmring/core.h b/arch/arm/mach-bcmring/core.h new file mode 100644 index 0000000000000..b197ba48e36e2 --- /dev/null +++ b/arch/arm/mach-bcmring/core.h @@ -0,0 +1,30 @@ +/* + * linux/arch/arm/mach-versatile/core.h + * + * Copyright (C) 2004 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* Portions copyright Broadcom 2008 */ +#ifndef __ASM_ARCH_BCMRING_H +#define __ASM_ARCH_BCMRING_H + +void __init bcmring_amba_init(void); +void __init bcmring_map_io(void); +void __init bcmring_init_irq(void); + +extern struct sys_timer bcmring_timer; +#endif diff --git a/arch/arm/mach-bcmring/include/cfg_global.h b/arch/arm/mach-bcmring/include/cfg_global.h new file mode 100644 index 0000000000000..f01da877148ef --- /dev/null +++ b/arch/arm/mach-bcmring/include/cfg_global.h @@ -0,0 +1,13 @@ +#ifndef _CFG_GLOBAL_H_ +#define _CFG_GLOBAL_H_ + +#include <cfg_global_defines.h> + +#define CFG_GLOBAL_CHIP BCM11107 +#define CFG_GLOBAL_CHIP_FAMILY CFG_GLOBAL_CHIP_FAMILY_BCMRING +#define CFG_GLOBAL_CHIP_REV 0xB0 +#define CFG_GLOBAL_RAM_SIZE 0x10000000 +#define CFG_GLOBAL_RAM_BASE 0x00000000 +#define CFG_GLOBAL_RAM_RESERVED_SIZE 0x000000 + +#endif /* _CFG_GLOBAL_H_ */ diff --git a/arch/arm/mach-bcmring/include/cfg_global_defines.h b/arch/arm/mach-bcmring/include/cfg_global_defines.h new file mode 100644 index 0000000000000..b5beb0b307349 --- /dev/null +++ b/arch/arm/mach-bcmring/include/cfg_global_defines.h @@ -0,0 +1,40 @@ +/***************************************************************************** +* Copyright 2006 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CFG_GLOBAL_DEFINES_H +#define CFG_GLOBAL_DEFINES_H + +/* CHIP */ +#define BCM1103 1 + +#define BCM1191 4 +#define BCM2153 5 +#define BCM2820 6 + +#define BCM2826 8 +#define FPGA11107 9 +#define BCM11107 10 +#define BCM11109 11 +#define BCM11170 12 +#define BCM11110 13 +#define BCM11211 14 + +/* CFG_GLOBAL_CHIP_FAMILY types */ +#define CFG_GLOBAL_CHIP_FAMILY_NONE 0 +#define CFG_GLOBAL_CHIP_FAMILY_BCM116X 2 +#define CFG_GLOBAL_CHIP_FAMILY_BCMRING 4 +#define CFG_GLOBAL_CHIP_FAMILY_BCM1103 8 + +#define IMAGE_HEADER_SIZE_CHECKSUM 4 +#endif diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h new file mode 100644 index 0000000000000..447eb340c6112 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/hardware.h @@ -0,0 +1,60 @@ +/* + * + * This file contains the hardware definitions of the BCMRing. + * + * Copyright (C) 1999 ARM Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <asm/sizes.h> +#include <mach/memory.h> +#include <cfg_global.h> +#include <mach/csp/mm_io.h> + +/* Hardware addresses of major areas. + * *_START is the physical address + * *_SIZE is the size of the region + * *_BASE is the virtual address + */ +#define RAM_START PHYS_OFFSET + +#define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED) +#define RAM_BASE PAGE_OFFSET + +#define pcibios_assign_all_busses() 1 + +/* Macros to make managing spinlocks a bit more controlled in terms of naming. */ +/* See reg_gpio.h, reg_irq.h, arch.c, gpio.c for example usage. */ +#if defined(__KERNEL__) +#define HW_DECLARE_SPINLOCK(name) DEFINE_SPINLOCK(bcmring_##name##_reg_lock); +#define HW_EXTERN_SPINLOCK(name) extern spinlock_t bcmring_##name##_reg_lock; +#define HW_IRQ_SAVE(name, val) spin_lock_irqsave(&bcmring_##name##_reg_lock, (val)) +#define HW_IRQ_RESTORE(name, val) spin_unlock_irqrestore(&bcmring_##name##_reg_lock, (val)) +#else +#define HW_DECLARE_SPINLOCK(name) +#define HW_EXTERN_SPINLOCK(name) +#define HW_IRQ_SAVE(name, val) {(void)(name); (void)(val); } +#define HW_IRQ_RESTORE(name, val) {(void)(name); (void)(val); } +#endif + +#ifndef HW_IO_PHYS_TO_VIRT +#define HW_IO_PHYS_TO_VIRT MM_IO_PHYS_TO_VIRT +#endif +#define HW_IO_VIRT_TO_PHYS MM_IO_VIRT_TO_PHYS + +#endif diff --git a/arch/arm/mach-bcmring/include/mach/system.h b/arch/arm/mach-bcmring/include/mach/system.h new file mode 100644 index 0000000000000..cdbf93c694a64 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/system.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) 1999 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include <mach/csp/chipcHw_inline.h> + +extern int bcmring_arch_warm_reboot; + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, char *cmd) +{ + printk("arch_reset:%c %x\n", mode, bcmring_arch_warm_reboot); + + if (mode == 'h') { + /* Reboot configured in proc entry */ + if (bcmring_arch_warm_reboot) { + printk("warm reset\n"); + /* Issue Warm reset (do not reset ethernet switch, keep alive) */ + chipcHw_reset(chipcHw_REG_SOFT_RESET_CHIP_WARM); + } else { + /* Force reset of everything */ + printk("force reset\n"); + chipcHw_reset(chipcHw_REG_SOFT_RESET_CHIP_SOFT); + } + } else { + /* Force reset of everything */ + printk("force reset\n"); + chipcHw_reset(chipcHw_REG_SOFT_RESET_CHIP_SOFT); + } +} + +#endif -- GitLab From 278a6752e869b0f4a03ce5ac0588b31b50712903 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:58:26 +0100 Subject: [PATCH 0974/1002] ARM: 5644/1: add bcmring core.c, clock.c, clock.h add core.c, clock.c, and clock.h in mach-bcmring implement timer init, clocksource init, amba device init implement clock set/get enable/disable API add dummy clkdev.h Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/clock.c | 224 ++++++++++++ arch/arm/mach-bcmring/clock.h | 33 ++ arch/arm/mach-bcmring/core.c | 367 ++++++++++++++++++++ arch/arm/mach-bcmring/include/mach/clkdev.h | 7 + 4 files changed, 631 insertions(+) create mode 100644 arch/arm/mach-bcmring/clock.c create mode 100644 arch/arm/mach-bcmring/clock.h create mode 100644 arch/arm/mach-bcmring/core.c create mode 100644 arch/arm/mach-bcmring/include/mach/clkdev.h diff --git a/arch/arm/mach-bcmring/clock.c b/arch/arm/mach-bcmring/clock.c new file mode 100644 index 0000000000000..14bafc38f2dcc --- /dev/null +++ b/arch/arm/mach-bcmring/clock.c @@ -0,0 +1,224 @@ +/***************************************************************************** +* Copyright 2001 - 2009 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/clk.h> +#include <linux/spinlock.h> +#include <mach/csp/hw_cfg.h> +#include <mach/csp/chipcHw_def.h> +#include <mach/csp/chipcHw_reg.h> +#include <mach/csp/chipcHw_inline.h> + +#include <asm/clkdev.h> + +#include "clock.h" + +#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) +#define clk_is_pll1(x) ((x)->type & CLK_TYPE_PLL1) +#define clk_is_pll2(x) ((x)->type & CLK_TYPE_PLL2) +#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE) +#define clk_is_bypassable(x) ((x)->type & CLK_TYPE_BYPASSABLE) + +#define clk_is_using_xtal(x) ((x)->mode & CLK_MODE_XTAL) + +static DEFINE_SPINLOCK(clk_lock); + +static void __clk_enable(struct clk *clk) +{ + if (!clk) + return; + + /* enable parent clock first */ + if (clk->parent) + __clk_enable(clk->parent); + + if (clk->use_cnt++ == 0) { + if (clk_is_pll1(clk)) { /* PLL1 */ + chipcHw_pll1Enable(clk->rate_hz, 0); + } else if (clk_is_pll2(clk)) { /* PLL2 */ + chipcHw_pll2Enable(clk->rate_hz); + } else if (clk_is_using_xtal(clk)) { /* source is crystal */ + if (!clk_is_primary(clk)) + chipcHw_bypassClockEnable(clk->csp_id); + } else { /* source is PLL */ + chipcHw_setClockEnable(clk->csp_id); + } + } +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + + if (!clk) + return -EINVAL; + + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); + + return 0; +} +EXPORT_SYMBOL(clk_enable); + +static void __clk_disable(struct clk *clk) +{ + if (!clk) + return; + + BUG_ON(clk->use_cnt == 0); + + if (--clk->use_cnt == 0) { + if (clk_is_pll1(clk)) { /* PLL1 */ + chipcHw_pll1Disable(); + } else if (clk_is_pll2(clk)) { /* PLL2 */ + chipcHw_pll2Disable(); + } else if (clk_is_using_xtal(clk)) { /* source is crystal */ + if (!clk_is_primary(clk)) + chipcHw_bypassClockDisable(clk->csp_id); + } else { /* source is PLL */ + chipcHw_setClockDisable(clk->csp_id); + } + } + + if (clk->parent) + __clk_disable(clk->parent); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (!clk) + return; + + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (!clk) + return 0; + + return clk->rate_hz; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned long actual; + unsigned long rate_hz; + + if (!clk) + return -EINVAL; + + if (!clk_is_programmable(clk)) + return -EINVAL; + + if (clk->use_cnt) + return -EBUSY; + + spin_lock_irqsave(&clk_lock, flags); + actual = clk->parent->rate_hz; + rate_hz = min(actual, rate); + spin_unlock_irqrestore(&clk_lock, flags); + + return rate_hz; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + unsigned long actual; + unsigned long rate_hz; + + if (!clk) + return -EINVAL; + + if (!clk_is_programmable(clk)) + return -EINVAL; + + if (clk->use_cnt) + return -EBUSY; + + spin_lock_irqsave(&clk_lock, flags); + actual = clk->parent->rate_hz; + rate_hz = min(actual, rate); + rate_hz = chipcHw_setClockFrequency(clk->csp_id, rate_hz); + clk->rate_hz = rate_hz; + spin_unlock_irqrestore(&clk_lock, flags); + + return 0; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + if (!clk) + return NULL; + + return clk->parent; +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + struct clk *old_parent; + + if (!clk || !parent) + return -EINVAL; + + if (!clk_is_primary(parent) || !clk_is_bypassable(clk)) + return -EINVAL; + + /* if more than one user, parent is not allowed */ + if (clk->use_cnt > 1) + return -EBUSY; + + if (clk->parent == parent) + return 0; + + spin_lock_irqsave(&clk_lock, flags); + old_parent = clk->parent; + clk->parent = parent; + if (clk_is_using_xtal(parent)) + clk->mode |= CLK_MODE_XTAL; + else + clk->mode &= (~CLK_MODE_XTAL); + + /* if clock is active */ + if (clk->use_cnt != 0) { + clk->use_cnt--; + /* enable clock with the new parent */ + __clk_enable(clk); + /* disable the old parent */ + __clk_disable(old_parent); + } + spin_unlock_irqrestore(&clk_lock, flags); + + return 0; +} +EXPORT_SYMBOL(clk_set_parent); diff --git a/arch/arm/mach-bcmring/clock.h b/arch/arm/mach-bcmring/clock.h new file mode 100644 index 0000000000000..5e0b981389736 --- /dev/null +++ b/arch/arm/mach-bcmring/clock.h @@ -0,0 +1,33 @@ +/***************************************************************************** +* Copyright 2001 - 2009 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ +#include <mach/csp/chipcHw_def.h> + +#define CLK_TYPE_PRIMARY 1 /* primary clock must NOT have a parent */ +#define CLK_TYPE_PLL1 2 /* PPL1 */ +#define CLK_TYPE_PLL2 4 /* PPL2 */ +#define CLK_TYPE_PROGRAMMABLE 8 /* programmable clock rate */ +#define CLK_TYPE_BYPASSABLE 16 /* parent can be changed */ + +#define CLK_MODE_XTAL 1 /* clock source is from crystal */ + +struct clk { + const char *name; /* clock name */ + unsigned int type; /* clock type */ + unsigned int mode; /* current mode */ + volatile int use_bypass; /* indicate if it's in bypass mode */ + chipcHw_CLOCK_e csp_id; /* clock ID for CSP CHIPC */ + unsigned long rate_hz; /* clock rate in Hz */ + unsigned int use_cnt; /* usage count */ + struct clk *parent; /* parent clock */ +}; diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c new file mode 100644 index 0000000000000..492c649f451ec --- /dev/null +++ b/arch/arm/mach-bcmring/core.c @@ -0,0 +1,367 @@ +/* + * derived from linux/arch/arm/mach-versatile/core.c + * linux/arch/arm/mach-bcmring/core.c + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* Portions copyright Broadcom 2008 */ + +#include <linux/init.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <linux/amba/bus.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> + +#include <linux/amba/bus.h> +#include <mach/csp/mm_addr.h> +#include <mach/hardware.h> +#include <asm/clkdev.h> +#include <linux/io.h> +#include <asm/irq.h> +#include <asm/hardware/arm_timer.h> +#include <asm/mach-types.h> + +#include <asm/mach/arch.h> +#include <asm/mach/flash.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> +#include <asm/mach/map.h> +#include <asm/mach/mmc.h> + +#include <cfg_global.h> + +#include "clock.h" + +#include <csp/secHw.h> +#include <mach/csp/secHw_def.h> +#include <mach/csp/chipcHw_inline.h> +#include <mach/csp/tmrHw_reg.h> + +#define AMBA_DEVICE(name, initname, base, plat, size) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .init_name = initname, \ + .platform_data = plat \ + }, \ + .res = { \ + .start = MM_ADDR_IO_##base, \ + .end = MM_ADDR_IO_##base + (size) - 1, \ + .flags = IORESOURCE_MEM \ + }, \ + .dma_mask = ~0, \ + .irq = { \ + IRQ_##base \ + } \ +} + + +AMBA_DEVICE(uartA, "uarta", UARTA, NULL, SZ_4K); +AMBA_DEVICE(uartB, "uartb", UARTB, NULL, SZ_4K); + +static struct clk pll1_clk = { + .name = "PLL1", + .type = CLK_TYPE_PRIMARY | CLK_TYPE_PLL1, + .rate_hz = 2000000000, + .use_cnt = 7, +}; + +static struct clk uart_clk = { + .name = "UART", + .type = CLK_TYPE_PROGRAMMABLE, + .csp_id = chipcHw_CLOCK_UART, + .rate_hz = HW_CFG_UART_CLK_HZ, + .parent = &pll1_clk, +}; + +static struct clk_lookup lookups[] = { + { /* UART0 */ + .dev_id = "uarta", + .clk = &uart_clk, + }, { /* UART1 */ + .dev_id = "uartb", + .clk = &uart_clk, + } +}; + +static struct amba_device *amba_devs[] __initdata = { + &uartA_device, + &uartB_device, +}; + +void __init bcmring_amba_init(void) +{ + int i; + u32 bus_clock; + +/* Linux is run initially in non-secure mode. Secure peripherals */ +/* generate FIQ, and must be handled in secure mode. Until we have */ +/* a linux security monitor implementation, keep everything in */ +/* non-secure mode. */ + chipcHw_busInterfaceClockEnable(chipcHw_REG_BUS_CLOCK_SPU); + secHw_setUnsecure(secHw_BLK_MASK_CHIP_CONTROL | + secHw_BLK_MASK_KEY_SCAN | + secHw_BLK_MASK_TOUCH_SCREEN | + secHw_BLK_MASK_UART0 | + secHw_BLK_MASK_UART1 | + secHw_BLK_MASK_WATCHDOG | + secHw_BLK_MASK_SPUM | + secHw_BLK_MASK_DDR2 | + secHw_BLK_MASK_SPU | + secHw_BLK_MASK_PKA | + secHw_BLK_MASK_RNG | + secHw_BLK_MASK_RTC | + secHw_BLK_MASK_OTP | + secHw_BLK_MASK_BOOT | + secHw_BLK_MASK_MPU | + secHw_BLK_MASK_TZCTRL | secHw_BLK_MASK_INTR); + + /* Only the devices attached to the AMBA bus are enabled just before the bus is */ + /* scanned and the drivers are loaded. The clocks need to be on for the AMBA bus */ + /* driver to access these blocks. The bus is probed, and the drivers are loaded. */ + /* FIXME Need to remove enable of PIF once CLCD clock enable used properly in FPGA. */ + bus_clock = chipcHw_REG_BUS_CLOCK_GE + | chipcHw_REG_BUS_CLOCK_SDIO0 | chipcHw_REG_BUS_CLOCK_SDIO1; + + chipcHw_busInterfaceClockEnable(bus_clock); + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } +} + +/* + * Where is the timer (VA)? + */ +#define TIMER0_VA_BASE MM_IO_BASE_TMR +#define TIMER1_VA_BASE (MM_IO_BASE_TMR + 0x20) +#define TIMER2_VA_BASE (MM_IO_BASE_TMR + 0x40) +#define TIMER3_VA_BASE (MM_IO_BASE_TMR + 0x60) + +/* Timer 0 - 25 MHz, Timer3 at bus clock rate, typically 150-166 MHz */ +#if defined(CONFIG_ARCH_FPGA11107) +/* fpga cpu/bus are currently 30 times slower so scale frequency as well to */ +/* slow down Linux's sense of time */ +#define TIMER0_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) +#define TIMER1_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) +#define TIMER3_FREQUENCY_MHZ (tmrHw_HIGH_FREQUENCY_MHZ * 30) +#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000 * 30) +#else +#define TIMER0_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ +#define TIMER1_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ +#define TIMER3_FREQUENCY_MHZ tmrHw_HIGH_FREQUENCY_MHZ +#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000) +#endif + +#define TICKS_PER_uSEC TIMER0_FREQUENCY_MHZ + +/* + * These are useconds NOT ticks. + * + */ +#define mSEC_1 1000 +#define mSEC_5 (mSEC_1 * 5) +#define mSEC_10 (mSEC_1 * 10) +#define mSEC_25 (mSEC_1 * 25) +#define SEC_1 (mSEC_1 * 1000) + +/* + * How long is the timer interval? + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) +#if TIMER_INTERVAL >= 0x100000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 8) +#define TIMER_DIVISOR (TIMER_CTRL_DIV256) +#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) +#elif TIMER_INTERVAL >= 0x10000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ +#define TIMER_DIVISOR (TIMER_CTRL_DIV16) +#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) +#else +#define TIMER_RELOAD (TIMER_INTERVAL) +#define TIMER_DIVISOR (TIMER_CTRL_DIV1) +#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) +#endif + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + unsigned long ctrl; + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); + + ctrl = TIMER_CTRL_PERIODIC; + ctrl |= + TIMER_DIVISOR | TIMER_CTRL_32BIT | TIMER_CTRL_IE | + TIMER_CTRL_ENABLE; + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ + ctrl = TIMER_CTRL_ONESHOT; + ctrl |= TIMER_DIVISOR | TIMER_CTRL_32BIT | TIMER_CTRL_IE; + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + ctrl = 0; + } + + writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL); +} + +static int timer_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL); + + writel(evt, TIMER0_VA_BASE + TIMER_LOAD); + writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL); + + return 0; +} + +static struct clock_event_device timer0_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, +}; + +/* + * IRQ handler for the timer + */ +static irqreturn_t bcmring_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &timer0_clockevent; + + writel(1, TIMER0_VA_BASE + TIMER_INTCLR); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction bcmring_timer_irq = { + .name = "bcmring Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcmring_timer_interrupt, +}; + +static cycle_t bcmring_get_cycles_timer1(void) +{ + return ~readl(TIMER1_VA_BASE + TIMER_VALUE); +} + +static cycle_t bcmring_get_cycles_timer3(void) +{ + return ~readl(TIMER3_VA_BASE + TIMER_VALUE); +} + +static struct clocksource clocksource_bcmring_timer1 = { + .name = "timer1", + .rating = 200, + .read = bcmring_get_cycles_timer1, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static struct clocksource clocksource_bcmring_timer3 = { + .name = "timer3", + .rating = 100, + .read = bcmring_get_cycles_timer3, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int __init bcmring_clocksource_init(void) +{ + /* setup timer1 as free-running clocksource */ + writel(0, TIMER1_VA_BASE + TIMER_CTRL); + writel(0xffffffff, TIMER1_VA_BASE + TIMER_LOAD); + writel(0xffffffff, TIMER1_VA_BASE + TIMER_VALUE); + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, + TIMER1_VA_BASE + TIMER_CTRL); + + clocksource_bcmring_timer1.mult = + clocksource_khz2mult(TIMER1_FREQUENCY_MHZ * 1000, + clocksource_bcmring_timer1.shift); + clocksource_register(&clocksource_bcmring_timer1); + + /* setup timer3 as free-running clocksource */ + writel(0, TIMER3_VA_BASE + TIMER_CTRL); + writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD); + writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE); + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, + TIMER3_VA_BASE + TIMER_CTRL); + + clocksource_bcmring_timer3.mult = + clocksource_khz2mult(TIMER3_FREQUENCY_KHZ, + clocksource_bcmring_timer3.shift); + clocksource_register(&clocksource_bcmring_timer3); + + return 0; +} + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +void __init bcmring_init_timer(void) +{ + printk(KERN_INFO "bcmring_init_timer\n"); + /* + * Initialise to a known state (all timers off) + */ + writel(0, TIMER0_VA_BASE + TIMER_CTRL); + writel(0, TIMER1_VA_BASE + TIMER_CTRL); + writel(0, TIMER2_VA_BASE + TIMER_CTRL); + writel(0, TIMER3_VA_BASE + TIMER_CTRL); + + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER0, &bcmring_timer_irq); + + bcmring_clocksource_init(); + + timer0_clockevent.mult = + div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); + timer0_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer0_clockevent); + timer0_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer0_clockevent); + + timer0_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&timer0_clockevent); +} + +struct sys_timer bcmring_timer = { + .init = bcmring_init_timer, +}; diff --git a/arch/arm/mach-bcmring/include/mach/clkdev.h b/arch/arm/mach-bcmring/include/mach/clkdev.h new file mode 100644 index 0000000000000..04b37a89801cf --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif -- GitLab From b7462d654f623738b4b3e03cff20f68b5b9a77f5 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:59:04 +0100 Subject: [PATCH 0975/1002] ARM: 5645/1: bcmring: add bcmring irq.c init irq and handler add irq controller register file and header files Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/csp/intcHw.h | 40 +++ .../include/mach/csp/intcHw_reg.h | 246 ++++++++++++++++++ arch/arm/mach-bcmring/include/mach/irqs.h | 132 ++++++++++ arch/arm/mach-bcmring/irq.c | 127 +++++++++ 4 files changed, 545 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/csp/intcHw.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h create mode 100644 arch/arm/mach-bcmring/include/mach/irqs.h create mode 100644 arch/arm/mach-bcmring/irq.c diff --git a/arch/arm/mach-bcmring/include/csp/intcHw.h b/arch/arm/mach-bcmring/include/csp/intcHw.h new file mode 100644 index 0000000000000..1c639c8ee08f3 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/intcHw.h @@ -0,0 +1,40 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + + +/****************************************************************************/ +/** +* @file intcHw.h +* +* @brief generic interrupt controller API +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef _INTCHW_H +#define _INTCHW_H + +/* ---- Include Files ---------------------------------------------------- */ +#include <mach/csp/intcHw_reg.h> + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ +static inline void intcHw_irq_disable(void *basep, uint32_t mask); +static inline void intcHw_irq_enable(void *basep, uint32_t mask); + +#endif /* _INTCHW_H */ + diff --git a/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h new file mode 100644 index 0000000000000..e01fc4607c913 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h @@ -0,0 +1,246 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file intcHw_reg.h +* +* @brief platform specific interrupt controller bit assignments +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef _INTCHW_REG_H +#define _INTCHW_REG_H + +/* ---- Include Files ---------------------------------------------------- */ +#include <csp/stdint.h> +#include <csp/reg.h> +#include <mach/csp/mm_io.h> + +/* ---- Public Constants and Types --------------------------------------- */ + +#define INTCHW_NUM_IRQ_PER_INTC 32 /* Maximum number of interrupt controllers */ +#define INTCHW_NUM_INTC 3 + +/* Defines for interrupt controllers. This simplifies and cleans up the function calls. */ +#define INTCHW_INTC0 ((void *)MM_IO_BASE_INTC0) +#define INTCHW_INTC1 ((void *)MM_IO_BASE_INTC1) +#define INTCHW_SINTC ((void *)MM_IO_BASE_SINTC) + +/* INTC0 - interrupt controller 0 */ +#define INTCHW_INTC0_PIF_BITNUM 31 /* Peripheral interface interrupt */ +#define INTCHW_INTC0_CLCD_BITNUM 30 /* LCD Controller interrupt */ +#define INTCHW_INTC0_GE_BITNUM 29 /* Graphic engine interrupt */ +#define INTCHW_INTC0_APM_BITNUM 28 /* Audio process module interrupt */ +#define INTCHW_INTC0_ESW_BITNUM 27 /* Ethernet switch interrupt */ +#define INTCHW_INTC0_SPIH_BITNUM 26 /* SPI host interrupt */ +#define INTCHW_INTC0_TIMER3_BITNUM 25 /* Timer3 interrupt */ +#define INTCHW_INTC0_TIMER2_BITNUM 24 /* Timer2 interrupt */ +#define INTCHW_INTC0_TIMER1_BITNUM 23 /* Timer1 interrupt */ +#define INTCHW_INTC0_TIMER0_BITNUM 22 /* Timer0 interrupt */ +#define INTCHW_INTC0_SDIOH1_BITNUM 21 /* SDIO1 host interrupt */ +#define INTCHW_INTC0_SDIOH0_BITNUM 20 /* SDIO0 host interrupt */ +#define INTCHW_INTC0_USBD_BITNUM 19 /* USB device interrupt */ +#define INTCHW_INTC0_USBH1_BITNUM 18 /* USB1 host interrupt */ +#define INTCHW_INTC0_USBHD2_BITNUM 17 /* USB host2/device2 interrupt */ +#define INTCHW_INTC0_VPM_BITNUM 16 /* Voice process module interrupt */ +#define INTCHW_INTC0_DMA1C7_BITNUM 15 /* DMA1 channel 7 interrupt */ +#define INTCHW_INTC0_DMA1C6_BITNUM 14 /* DMA1 channel 6 interrupt */ +#define INTCHW_INTC0_DMA1C5_BITNUM 13 /* DMA1 channel 5 interrupt */ +#define INTCHW_INTC0_DMA1C4_BITNUM 12 /* DMA1 channel 4 interrupt */ +#define INTCHW_INTC0_DMA1C3_BITNUM 11 /* DMA1 channel 3 interrupt */ +#define INTCHW_INTC0_DMA1C2_BITNUM 10 /* DMA1 channel 2 interrupt */ +#define INTCHW_INTC0_DMA1C1_BITNUM 9 /* DMA1 channel 1 interrupt */ +#define INTCHW_INTC0_DMA1C0_BITNUM 8 /* DMA1 channel 0 interrupt */ +#define INTCHW_INTC0_DMA0C7_BITNUM 7 /* DMA0 channel 7 interrupt */ +#define INTCHW_INTC0_DMA0C6_BITNUM 6 /* DMA0 channel 6 interrupt */ +#define INTCHW_INTC0_DMA0C5_BITNUM 5 /* DMA0 channel 5 interrupt */ +#define INTCHW_INTC0_DMA0C4_BITNUM 4 /* DMA0 channel 4 interrupt */ +#define INTCHW_INTC0_DMA0C3_BITNUM 3 /* DMA0 channel 3 interrupt */ +#define INTCHW_INTC0_DMA0C2_BITNUM 2 /* DMA0 channel 2 interrupt */ +#define INTCHW_INTC0_DMA0C1_BITNUM 1 /* DMA0 channel 1 interrupt */ +#define INTCHW_INTC0_DMA0C0_BITNUM 0 /* DMA0 channel 0 interrupt */ + +#define INTCHW_INTC0_PIF (1<<INTCHW_INTC0_PIF_BITNUM) +#define INTCHW_INTC0_CLCD (1<<INTCHW_INTC0_CLCD_BITNUM) +#define INTCHW_INTC0_GE (1<<INTCHW_INTC0_GE_BITNUM) +#define INTCHW_INTC0_APM (1<<INTCHW_INTC0_APM_BITNUM) +#define INTCHW_INTC0_ESW (1<<INTCHW_INTC0_ESW_BITNUM) +#define INTCHW_INTC0_SPIH (1<<INTCHW_INTC0_SPIH_BITNUM) +#define INTCHW_INTC0_TIMER3 (1<<INTCHW_INTC0_TIMER3_BITNUM) +#define INTCHW_INTC0_TIMER2 (1<<INTCHW_INTC0_TIMER2_BITNUM) +#define INTCHW_INTC0_TIMER1 (1<<INTCHW_INTC0_TIMER1_BITNUM) +#define INTCHW_INTC0_TIMER0 (1<<INTCHW_INTC0_TIMER0_BITNUM) +#define INTCHW_INTC0_SDIOH1 (1<<INTCHW_INTC0_SDIOH1_BITNUM) +#define INTCHW_INTC0_SDIOH0 (1<<INTCHW_INTC0_SDIOH0_BITNUM) +#define INTCHW_INTC0_USBD (1<<INTCHW_INTC0_USBD_BITNUM) +#define INTCHW_INTC0_USBH1 (1<<INTCHW_INTC0_USBH1_BITNUM) +#define INTCHW_INTC0_USBHD2 (1<<INTCHW_INTC0_USBHD2_BITNUM) +#define INTCHW_INTC0_VPM (1<<INTCHW_INTC0_VPM_BITNUM) +#define INTCHW_INTC0_DMA1C7 (1<<INTCHW_INTC0_DMA1C7_BITNUM) +#define INTCHW_INTC0_DMA1C6 (1<<INTCHW_INTC0_DMA1C6_BITNUM) +#define INTCHW_INTC0_DMA1C5 (1<<INTCHW_INTC0_DMA1C5_BITNUM) +#define INTCHW_INTC0_DMA1C4 (1<<INTCHW_INTC0_DMA1C4_BITNUM) +#define INTCHW_INTC0_DMA1C3 (1<<INTCHW_INTC0_DMA1C3_BITNUM) +#define INTCHW_INTC0_DMA1C2 (1<<INTCHW_INTC0_DMA1C2_BITNUM) +#define INTCHW_INTC0_DMA1C1 (1<<INTCHW_INTC0_DMA1C1_BITNUM) +#define INTCHW_INTC0_DMA1C0 (1<<INTCHW_INTC0_DMA1C0_BITNUM) +#define INTCHW_INTC0_DMA0C7 (1<<INTCHW_INTC0_DMA0C7_BITNUM) +#define INTCHW_INTC0_DMA0C6 (1<<INTCHW_INTC0_DMA0C6_BITNUM) +#define INTCHW_INTC0_DMA0C5 (1<<INTCHW_INTC0_DMA0C5_BITNUM) +#define INTCHW_INTC0_DMA0C4 (1<<INTCHW_INTC0_DMA0C4_BITNUM) +#define INTCHW_INTC0_DMA0C3 (1<<INTCHW_INTC0_DMA0C3_BITNUM) +#define INTCHW_INTC0_DMA0C2 (1<<INTCHW_INTC0_DMA0C2_BITNUM) +#define INTCHW_INTC0_DMA0C1 (1<<INTCHW_INTC0_DMA0C1_BITNUM) +#define INTCHW_INTC0_DMA0C0 (1<<INTCHW_INTC0_DMA0C0_BITNUM) + +/* INTC1 - interrupt controller 1 */ +#define INTCHW_INTC1_DDRVPMP_BITNUM 27 /* DDR and VPM PLL clock phase relationship interupt (Not for A0) */ +#define INTCHW_INTC1_DDRVPMT_BITNUM 26 /* DDR and VPM HW phase align timeout interrupt (Not for A0) */ +#define INTCHW_INTC1_DDRP_BITNUM 26 /* DDR and PLL clock phase relationship interupt (For A0 only)) */ +#define INTCHW_INTC1_RTC2_BITNUM 25 /* Real time clock tamper interrupt */ +#define INTCHW_INTC1_VDEC_BITNUM 24 /* Hantro Video Decoder interrupt */ +/* Bits 13-23 are non-secure versions of the corresponding secure bits in SINTC bits 0-10. */ +#define INTCHW_INTC1_SPUM_BITNUM 23 /* Secure process module interrupt */ +#define INTCHW_INTC1_RTC1_BITNUM 22 /* Real time clock one-shot interrupt */ +#define INTCHW_INTC1_RTC0_BITNUM 21 /* Real time clock periodic interrupt */ +#define INTCHW_INTC1_RNG_BITNUM 20 /* Random number generator interrupt */ +#define INTCHW_INTC1_FMPU_BITNUM 19 /* Flash memory parition unit interrupt */ +#define INTCHW_INTC1_VMPU_BITNUM 18 /* VRAM memory partition interrupt */ +#define INTCHW_INTC1_DMPU_BITNUM 17 /* DDR2 memory partition interrupt */ +#define INTCHW_INTC1_KEYC_BITNUM 16 /* Key pad controller interrupt */ +#define INTCHW_INTC1_TSC_BITNUM 15 /* Touch screen controller interrupt */ +#define INTCHW_INTC1_UART0_BITNUM 14 /* UART 0 */ +#define INTCHW_INTC1_WDOG_BITNUM 13 /* Watchdog timer interrupt */ + +#define INTCHW_INTC1_UART1_BITNUM 12 /* UART 1 */ +#define INTCHW_INTC1_PMUIRQ_BITNUM 11 /* ARM performance monitor interrupt */ +#define INTCHW_INTC1_COMMRX_BITNUM 10 /* ARM DDC receive interrupt */ +#define INTCHW_INTC1_COMMTX_BITNUM 9 /* ARM DDC transmit interrupt */ +#define INTCHW_INTC1_FLASHC_BITNUM 8 /* Flash controller interrupt */ +#define INTCHW_INTC1_GPHY_BITNUM 7 /* Gigabit Phy interrupt */ +#define INTCHW_INTC1_SPIS_BITNUM 6 /* SPI slave interrupt */ +#define INTCHW_INTC1_I2CS_BITNUM 5 /* I2C slave interrupt */ +#define INTCHW_INTC1_I2CH_BITNUM 4 /* I2C host interrupt */ +#define INTCHW_INTC1_I2S1_BITNUM 3 /* I2S1 interrupt */ +#define INTCHW_INTC1_I2S0_BITNUM 2 /* I2S0 interrupt */ +#define INTCHW_INTC1_GPIO1_BITNUM 1 /* GPIO bit 64//32 combined interrupt */ +#define INTCHW_INTC1_GPIO0_BITNUM 0 /* GPIO bit 31//0 combined interrupt */ + +#define INTCHW_INTC1_DDRVPMT (1<<INTCHW_INTC1_DDRVPMT_BITNUM) +#define INTCHW_INTC1_DDRVPMP (1<<INTCHW_INTC1_DDRVPMP_BITNUM) +#define INTCHW_INTC1_DDRP (1<<INTCHW_INTC1_DDRP_BITNUM) +#define INTCHW_INTC1_VDEC (1<<INTCHW_INTC1_VDEC_BITNUM) +#define INTCHW_INTC1_SPUM (1<<INTCHW_INTC1_SPUM_BITNUM) +#define INTCHW_INTC1_RTC2 (1<<INTCHW_INTC1_RTC2_BITNUM) +#define INTCHW_INTC1_RTC1 (1<<INTCHW_INTC1_RTC1_BITNUM) +#define INTCHW_INTC1_RTC0 (1<<INTCHW_INTC1_RTC0_BITNUM) +#define INTCHW_INTC1_RNG (1<<INTCHW_INTC1_RNG_BITNUM) +#define INTCHW_INTC1_FMPU (1<<INTCHW_INTC1_FMPU_BITNUM) +#define INTCHW_INTC1_IMPU (1<<INTCHW_INTC1_IMPU_BITNUM) +#define INTCHW_INTC1_DMPU (1<<INTCHW_INTC1_DMPU_BITNUM) +#define INTCHW_INTC1_KEYC (1<<INTCHW_INTC1_KEYC_BITNUM) +#define INTCHW_INTC1_TSC (1<<INTCHW_INTC1_TSC_BITNUM) +#define INTCHW_INTC1_UART0 (1<<INTCHW_INTC1_UART0_BITNUM) +#define INTCHW_INTC1_WDOG (1<<INTCHW_INTC1_WDOG_BITNUM) +#define INTCHW_INTC1_UART1 (1<<INTCHW_INTC1_UART1_BITNUM) +#define INTCHW_INTC1_PMUIRQ (1<<INTCHW_INTC1_PMUIRQ_BITNUM) +#define INTCHW_INTC1_COMMRX (1<<INTCHW_INTC1_COMMRX_BITNUM) +#define INTCHW_INTC1_COMMTX (1<<INTCHW_INTC1_COMMTX_BITNUM) +#define INTCHW_INTC1_FLASHC (1<<INTCHW_INTC1_FLASHC_BITNUM) +#define INTCHW_INTC1_GPHY (1<<INTCHW_INTC1_GPHY_BITNUM) +#define INTCHW_INTC1_SPIS (1<<INTCHW_INTC1_SPIS_BITNUM) +#define INTCHW_INTC1_I2CS (1<<INTCHW_INTC1_I2CS_BITNUM) +#define INTCHW_INTC1_I2CH (1<<INTCHW_INTC1_I2CH_BITNUM) +#define INTCHW_INTC1_I2S1 (1<<INTCHW_INTC1_I2S1_BITNUM) +#define INTCHW_INTC1_I2S0 (1<<INTCHW_INTC1_I2S0_BITNUM) +#define INTCHW_INTC1_GPIO1 (1<<INTCHW_INTC1_GPIO1_BITNUM) +#define INTCHW_INTC1_GPIO0 (1<<INTCHW_INTC1_GPIO0_BITNUM) + +/* SINTC secure int controller */ +#define INTCHW_SINTC_RTC2_BITNUM 15 /* Real time clock tamper interrupt */ +#define INTCHW_SINTC_TIMER3_BITNUM 14 /* Secure timer3 interrupt */ +#define INTCHW_SINTC_TIMER2_BITNUM 13 /* Secure timer2 interrupt */ +#define INTCHW_SINTC_TIMER1_BITNUM 12 /* Secure timer1 interrupt */ +#define INTCHW_SINTC_TIMER0_BITNUM 11 /* Secure timer0 interrupt */ +#define INTCHW_SINTC_SPUM_BITNUM 10 /* Secure process module interrupt */ +#define INTCHW_SINTC_RTC1_BITNUM 9 /* Real time clock one-shot interrupt */ +#define INTCHW_SINTC_RTC0_BITNUM 8 /* Real time clock periodic interrupt */ +#define INTCHW_SINTC_RNG_BITNUM 7 /* Random number generator interrupt */ +#define INTCHW_SINTC_FMPU_BITNUM 6 /* Flash memory parition unit interrupt */ +#define INTCHW_SINTC_VMPU_BITNUM 5 /* VRAM memory partition interrupt */ +#define INTCHW_SINTC_DMPU_BITNUM 4 /* DDR2 memory partition interrupt */ +#define INTCHW_SINTC_KEYC_BITNUM 3 /* Key pad controller interrupt */ +#define INTCHW_SINTC_TSC_BITNUM 2 /* Touch screen controller interrupt */ +#define INTCHW_SINTC_UART0_BITNUM 1 /* UART0 interrupt */ +#define INTCHW_SINTC_WDOG_BITNUM 0 /* Watchdog timer interrupt */ + +#define INTCHW_SINTC_TIMER3 (1<<INTCHW_SINTC_TIMER3_BITNUM) +#define INTCHW_SINTC_TIMER2 (1<<INTCHW_SINTC_TIMER2_BITNUM) +#define INTCHW_SINTC_TIMER1 (1<<INTCHW_SINTC_TIMER1_BITNUM) +#define INTCHW_SINTC_TIMER0 (1<<INTCHW_SINTC_TIMER0_BITNUM) +#define INTCHW_SINTC_SPUM (1<<INTCHW_SINTC_SPUM_BITNUM) +#define INTCHW_SINTC_RTC2 (1<<INTCHW_SINTC_RTC2_BITNUM) +#define INTCHW_SINTC_RTC1 (1<<INTCHW_SINTC_RTC1_BITNUM) +#define INTCHW_SINTC_RTC0 (1<<INTCHW_SINTC_RTC0_BITNUM) +#define INTCHW_SINTC_RNG (1<<INTCHW_SINTC_RNG_BITNUM) +#define INTCHW_SINTC_FMPU (1<<INTCHW_SINTC_FMPU_BITNUM) +#define INTCHW_SINTC_IMPU (1<<INTCHW_SINTC_IMPU_BITNUM) +#define INTCHW_SINTC_DMPU (1<<INTCHW_SINTC_DMPU_BITNUM) +#define INTCHW_SINTC_KEYC (1<<INTCHW_SINTC_KEYC_BITNUM) +#define INTCHW_SINTC_TSC (1<<INTCHW_SINTC_TSC_BITNUM) +#define INTCHW_SINTC_UART0 (1<<INTCHW_SINTC_UART0_BITNUM) +#define INTCHW_SINTC_WDOG (1<<INTCHW_SINTC_WDOG_BITNUM) + +/* PL192 Vectored Interrupt Controller (VIC) layout */ +#define INTCHW_IRQSTATUS 0x00 /* IRQ status register */ +#define INTCHW_FIQSTATUS 0x04 /* FIQ status register */ +#define INTCHW_RAWINTR 0x08 /* Raw Interrupt Status register */ +#define INTCHW_INTSELECT 0x0c /* Interrupt Select Register */ +#define INTCHW_INTENABLE 0x10 /* Interrupt Enable Register */ +#define INTCHW_INTENCLEAR 0x14 /* Interrupt Enable Clear Register */ +#define INTCHW_SOFTINT 0x18 /* Soft Interrupt Register */ +#define INTCHW_SOFTINTCLEAR 0x1c /* Soft Interrupt Clear Register */ +#define INTCHW_PROTECTION 0x20 /* Protection Enable Register */ +#define INTCHW_SWPRIOMASK 0x24 /* Software Priority Mask Register */ +#define INTCHW_PRIODAISY 0x28 /* Priority Daisy Chain Register */ +#define INTCHW_VECTADDR0 0x100 /* Vector Address Registers */ +#define INTCHW_VECTPRIO0 0x200 /* Vector Priority Registers 0-31 */ +#define INTCHW_ADDRESS 0xf00 /* Vector Address Register 0-31 */ +#define INTCHW_PID 0xfe0 /* Peripheral ID Register 0-3 */ +#define INTCHW_PCELLID 0xff0 /* PrimeCell ID Register 0-3 */ + +/* Example Usage: intcHw_irq_enable(INTCHW_INTC0, INTCHW_INTC0_TIMER0); */ +/* intcHw_irq_clear(INTCHW_INTC0, INTCHW_INTC0_TIMER0); */ +/* uint32_t bits = intcHw_irq_status(INTCHW_INTC0); */ +/* uint32_t bits = intcHw_irq_raw_status(INTCHW_INTC0); */ + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ +/* Clear one or more IRQ interrupts. */ +static inline void intcHw_irq_disable(void *basep, uint32_t mask) +{ + __REG32(basep + INTCHW_INTENCLEAR) = mask; +} + +/* Enables one or more IRQ interrupts. */ +static inline void intcHw_irq_enable(void *basep, uint32_t mask) +{ + __REG32(basep + INTCHW_INTENABLE) = mask; +} + +#endif /* _INTCHW_REG_H */ diff --git a/arch/arm/mach-bcmring/include/mach/irqs.h b/arch/arm/mach-bcmring/include/mach/irqs.h new file mode 100644 index 0000000000000..b279b825d4a7a --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/irqs.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2007 Broadcom + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(ARCH_BCMRING_IRQS_H) +#define ARCH_BCMRING_IRQS_H + +/* INTC0 - interrupt controller 0 */ +#define IRQ_INTC0_START 0 +#define IRQ_DMA0C0 0 /* DMA0 channel 0 interrupt */ +#define IRQ_DMA0C1 1 /* DMA0 channel 1 interrupt */ +#define IRQ_DMA0C2 2 /* DMA0 channel 2 interrupt */ +#define IRQ_DMA0C3 3 /* DMA0 channel 3 interrupt */ +#define IRQ_DMA0C4 4 /* DMA0 channel 4 interrupt */ +#define IRQ_DMA0C5 5 /* DMA0 channel 5 interrupt */ +#define IRQ_DMA0C6 6 /* DMA0 channel 6 interrupt */ +#define IRQ_DMA0C7 7 /* DMA0 channel 7 interrupt */ +#define IRQ_DMA1C0 8 /* DMA1 channel 0 interrupt */ +#define IRQ_DMA1C1 9 /* DMA1 channel 1 interrupt */ +#define IRQ_DMA1C2 10 /* DMA1 channel 2 interrupt */ +#define IRQ_DMA1C3 11 /* DMA1 channel 3 interrupt */ +#define IRQ_DMA1C4 12 /* DMA1 channel 4 interrupt */ +#define IRQ_DMA1C5 13 /* DMA1 channel 5 interrupt */ +#define IRQ_DMA1C6 14 /* DMA1 channel 6 interrupt */ +#define IRQ_DMA1C7 15 /* DMA1 channel 7 interrupt */ +#define IRQ_VPM 16 /* Voice process module interrupt */ +#define IRQ_USBHD2 17 /* USB host2/device2 interrupt */ +#define IRQ_USBH1 18 /* USB1 host interrupt */ +#define IRQ_USBD 19 /* USB device interrupt */ +#define IRQ_SDIOH0 20 /* SDIO0 host interrupt */ +#define IRQ_SDIOH1 21 /* SDIO1 host interrupt */ +#define IRQ_TIMER0 22 /* Timer0 interrupt */ +#define IRQ_TIMER1 23 /* Timer1 interrupt */ +#define IRQ_TIMER2 24 /* Timer2 interrupt */ +#define IRQ_TIMER3 25 /* Timer3 interrupt */ +#define IRQ_SPIH 26 /* SPI host interrupt */ +#define IRQ_ESW 27 /* Ethernet switch interrupt */ +#define IRQ_APM 28 /* Audio process module interrupt */ +#define IRQ_GE 29 /* Graphic engine interrupt */ +#define IRQ_CLCD 30 /* LCD Controller interrupt */ +#define IRQ_PIF 31 /* Peripheral interface interrupt */ +#define IRQ_INTC0_END 31 + +/* INTC1 - interrupt controller 1 */ +#define IRQ_INTC1_START 32 +#define IRQ_GPIO0 32 /* 0 GPIO bit 31//0 combined interrupt */ +#define IRQ_GPIO1 33 /* 1 GPIO bit 64//32 combined interrupt */ +#define IRQ_I2S0 34 /* 2 I2S0 interrupt */ +#define IRQ_I2S1 35 /* 3 I2S1 interrupt */ +#define IRQ_I2CH 36 /* 4 I2C host interrupt */ +#define IRQ_I2CS 37 /* 5 I2C slave interrupt */ +#define IRQ_SPIS 38 /* 6 SPI slave interrupt */ +#define IRQ_GPHY 39 /* 7 Gigabit Phy interrupt */ +#define IRQ_FLASHC 40 /* 8 Flash controller interrupt */ +#define IRQ_COMMTX 41 /* 9 ARM DDC transmit interrupt */ +#define IRQ_COMMRX 42 /* 10 ARM DDC receive interrupt */ +#define IRQ_PMUIRQ 43 /* 11 ARM performance monitor interrupt */ +#define IRQ_UARTB 44 /* 12 UARTB */ +#define IRQ_WATCHDOG 45 /* 13 Watchdog timer interrupt */ +#define IRQ_UARTA 46 /* 14 UARTA */ +#define IRQ_TSC 47 /* 15 Touch screen controller interrupt */ +#define IRQ_KEYC 48 /* 16 Key pad controller interrupt */ +#define IRQ_DMPU 49 /* 17 DDR2 memory partition interrupt */ +#define IRQ_VMPU 50 /* 18 VRAM memory partition interrupt */ +#define IRQ_FMPU 51 /* 19 Flash memory parition unit interrupt */ +#define IRQ_RNG 52 /* 20 Random number generator interrupt */ +#define IRQ_RTC0 53 /* 21 Real time clock periodic interrupt */ +#define IRQ_RTC1 54 /* 22 Real time clock one-shot interrupt */ +#define IRQ_SPUM 55 /* 23 Secure process module interrupt */ +#define IRQ_VDEC 56 /* 24 Hantro video decoder interrupt */ +#define IRQ_RTC2 57 /* 25 Real time clock tamper interrupt */ +#define IRQ_DDRP 58 /* 26 DDR Panic interrupt */ +#define IRQ_INTC1_END 58 + +/* SINTC secure int controller */ +#define IRQ_SINTC_START 59 +#define IRQ_SEC_WATCHDOG 59 /* 0 Watchdog timer interrupt */ +#define IRQ_SEC_UARTA 60 /* 1 UARTA interrupt */ +#define IRQ_SEC_TSC 61 /* 2 Touch screen controller interrupt */ +#define IRQ_SEC_KEYC 62 /* 3 Key pad controller interrupt */ +#define IRQ_SEC_DMPU 63 /* 4 DDR2 memory partition interrupt */ +#define IRQ_SEC_VMPU 64 /* 5 VRAM memory partition interrupt */ +#define IRQ_SEC_FMPU 65 /* 6 Flash memory parition unit interrupt */ +#define IRQ_SEC_RNG 66 /* 7 Random number generator interrupt */ +#define IRQ_SEC_RTC0 67 /* 8 Real time clock periodic interrupt */ +#define IRQ_SEC_RTC1 68 /* 9 Real time clock one-shot interrupt */ +#define IRQ_SEC_SPUM 69 /* 10 Secure process module interrupt */ +#define IRQ_SEC_TIMER0 70 /* 11 Secure timer0 interrupt */ +#define IRQ_SEC_TIMER1 71 /* 12 Secure timer1 interrupt */ +#define IRQ_SEC_TIMER2 72 /* 13 Secure timer2 interrupt */ +#define IRQ_SEC_TIMER3 73 /* 14 Secure timer3 interrupt */ +#define IRQ_SEC_RTC2 74 /* 15 Real time clock tamper interrupt */ + +#define IRQ_SINTC_END 74 + +/* Note: there are 3 INTC registers of 32 bits each. So internal IRQs could go from 0-95 */ +/* Since IRQs are typically viewed in decimal, we start the gpio based IRQs off at 100 */ +/* to make the mapping easy for humans to decipher. */ + +#define IRQ_GPIO_0 100 + +#define NUM_INTERNAL_IRQS (IRQ_SINTC_END+1) + +/* I couldn't get the gpioHw_reg.h file to be included cleanly, so I hardcoded it */ +/* define NUM_GPIO_IRQS GPIOHW_TOTAL_NUM_PINS */ +#define NUM_GPIO_IRQS 62 + +#define NR_IRQS (IRQ_GPIO_0 + NUM_GPIO_IRQS) + +#define IRQ_UNKNOWN -1 + +/* Tune these bits to preclude noisy or unsupported interrupt sources as required. */ +#define IRQ_INTC0_VALID_MASK 0xffffffff +#define IRQ_INTC1_VALID_MASK 0x07ffffff +#define IRQ_SINTC_VALID_MASK 0x0000ffff + +#endif /* ARCH_BCMRING_IRQS_H */ diff --git a/arch/arm/mach-bcmring/irq.c b/arch/arm/mach-bcmring/irq.c new file mode 100644 index 0000000000000..dc1c4939b0ced --- /dev/null +++ b/arch/arm/mach-bcmring/irq.c @@ -0,0 +1,127 @@ +/* + * + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/stddef.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/version.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <asm/irq.h> + +#include <asm/mach/irq.h> +#include <mach/csp/intcHw_reg.h> +#include <mach/csp/mm_io.h> + +static void bcmring_mask_irq0(unsigned int irq) +{ + writel(1 << (irq - IRQ_INTC0_START), + MM_IO_BASE_INTC0 + INTCHW_INTENCLEAR); +} + +static void bcmring_unmask_irq0(unsigned int irq) +{ + writel(1 << (irq - IRQ_INTC0_START), + MM_IO_BASE_INTC0 + INTCHW_INTENABLE); +} + +static void bcmring_mask_irq1(unsigned int irq) +{ + writel(1 << (irq - IRQ_INTC1_START), + MM_IO_BASE_INTC1 + INTCHW_INTENCLEAR); +} + +static void bcmring_unmask_irq1(unsigned int irq) +{ + writel(1 << (irq - IRQ_INTC1_START), + MM_IO_BASE_INTC1 + INTCHW_INTENABLE); +} + +static void bcmring_mask_irq2(unsigned int irq) +{ + writel(1 << (irq - IRQ_SINTC_START), + MM_IO_BASE_SINTC + INTCHW_INTENCLEAR); +} + +static void bcmring_unmask_irq2(unsigned int irq) +{ + writel(1 << (irq - IRQ_SINTC_START), + MM_IO_BASE_SINTC + INTCHW_INTENABLE); +} + +static struct irq_chip bcmring_irq0_chip = { + .typename = "ARM-INTC0", + .ack = bcmring_mask_irq0, + .mask = bcmring_mask_irq0, /* mask a specific interrupt, blocking its delivery. */ + .unmask = bcmring_unmask_irq0, /* unmaks an interrupt */ +}; + +static struct irq_chip bcmring_irq1_chip = { + .typename = "ARM-INTC1", + .ack = bcmring_mask_irq1, + .mask = bcmring_mask_irq1, + .unmask = bcmring_unmask_irq1, +}; + +static struct irq_chip bcmring_irq2_chip = { + .typename = "ARM-SINTC", + .ack = bcmring_mask_irq2, + .mask = bcmring_mask_irq2, + .unmask = bcmring_unmask_irq2, +}; + +static void vic_init(void __iomem *base, struct irq_chip *chip, + unsigned int irq_start, unsigned int vic_sources) +{ + unsigned int i; + for (i = 0; i < 32; i++) { + unsigned int irq = irq_start + i; + set_irq_chip(irq, chip); + set_irq_chip_data(irq, base); + + if (vic_sources & (1 << i)) { + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } + writel(0, base + INTCHW_INTSELECT); + writel(0, base + INTCHW_INTENABLE); + writel(~0, base + INTCHW_INTENCLEAR); + writel(0, base + INTCHW_IRQSTATUS); + writel(~0, base + INTCHW_SOFTINTCLEAR); +} + +void __init bcmring_init_irq(void) +{ + vic_init((void __iomem *)MM_IO_BASE_INTC0, &bcmring_irq0_chip, + IRQ_INTC0_START, IRQ_INTC0_VALID_MASK); + vic_init((void __iomem *)MM_IO_BASE_INTC1, &bcmring_irq1_chip, + IRQ_INTC1_START, IRQ_INTC1_VALID_MASK); + vic_init((void __iomem *)MM_IO_BASE_SINTC, &bcmring_irq2_chip, + IRQ_SINTC_START, IRQ_SINTC_VALID_MASK); + + /* special cases */ + if (INTCHW_INTC1_GPIO0 & IRQ_INTC1_VALID_MASK) { + set_irq_handler(IRQ_GPIO0, handle_simple_irq); + } + if (INTCHW_INTC1_GPIO1 & IRQ_INTC1_VALID_MASK) { + set_irq_handler(IRQ_GPIO1, handle_simple_irq); + } +} -- GitLab From 661f78d80969eefb25a0e99c08c0eba81b37861e Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:59:57 +0100 Subject: [PATCH 0976/1002] ARM: 5646/1: bcmring: add mach-bcmring/mm.c and memory headers memory map addresses memory map description and init functions Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../mach-bcmring/include/mach/csp/mm_addr.h | 101 ++++++++++++ .../arm/mach-bcmring/include/mach/csp/mm_io.h | 147 ++++++++++++++++++ arch/arm/mach-bcmring/include/mach/memory.h | 33 ++++ .../include/mach/memory_settings.h | 67 ++++++++ arch/arm/mach-bcmring/include/mach/vmalloc.h | 25 +++ arch/arm/mach-bcmring/mm.c | 56 +++++++ 6 files changed, 429 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/csp/mm_addr.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/mm_io.h create mode 100644 arch/arm/mach-bcmring/include/mach/memory.h create mode 100644 arch/arm/mach-bcmring/include/mach/memory_settings.h create mode 100644 arch/arm/mach-bcmring/include/mach/vmalloc.h create mode 100644 arch/arm/mach-bcmring/mm.c diff --git a/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h b/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h new file mode 100644 index 0000000000000..86bb58d4f58c3 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h @@ -0,0 +1,101 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file mm_addr.h +* +* @brief Memory Map address defintions +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef _MM_ADDR_H +#define _MM_ADDR_H + +/* ---- Include Files ---------------------------------------------------- */ + +#if !defined(CSP_SIMULATION) +#include <cfg_global.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ + +/* Memory Map address definitions */ + +#define MM_ADDR_DDR 0x00000000 + +#define MM_ADDR_IO_VPM_EXTMEM_RSVD 0x0F000000 /* 16 MB - Reserved external memory for VPM use */ + +#define MM_ADDR_IO_FLASHC 0x20000000 +#define MM_ADDR_IO_BROM 0x30000000 +#define MM_ADDR_IO_ARAM 0x30100000 /* 64 KB - extra cycle latency - WS switch */ +#define MM_ADDR_IO_DMA0 0x30200000 +#define MM_ADDR_IO_DMA1 0x30300000 +#define MM_ADDR_IO_ESW 0x30400000 +#define MM_ADDR_IO_CLCD 0x30500000 +#define MM_ADDR_IO_PIF 0x30580000 +#define MM_ADDR_IO_APM 0x30600000 +#define MM_ADDR_IO_SPUM 0x30700000 +#define MM_ADDR_IO_VPM_PROG 0x30800000 +#define MM_ADDR_IO_VPM_DATA 0x30A00000 +#define MM_ADDR_IO_VRAM 0x40000000 /* 64 KB - security block in front of it */ +#define MM_ADDR_IO_CHIPC 0x80000000 +#define MM_ADDR_IO_UMI 0x80001000 +#define MM_ADDR_IO_NAND 0x80001800 +#define MM_ADDR_IO_LEDM 0x80002000 +#define MM_ADDR_IO_PWM 0x80002040 +#define MM_ADDR_IO_VINTC 0x80003000 +#define MM_ADDR_IO_GPIO0 0x80004000 +#define MM_ADDR_IO_GPIO1 0x80004800 +#define MM_ADDR_IO_I2CS 0x80005000 +#define MM_ADDR_IO_SPIS 0x80006000 +#define MM_ADDR_IO_HPM 0x80007400 +#define MM_ADDR_IO_HPM_REMAP 0x80007800 +#define MM_ADDR_IO_TZPC 0x80008000 +#define MM_ADDR_IO_MPU 0x80009000 +#define MM_ADDR_IO_SPUMP 0x8000a000 +#define MM_ADDR_IO_PKA 0x8000b000 +#define MM_ADDR_IO_RNG 0x8000c000 +#define MM_ADDR_IO_KEYC 0x8000d000 +#define MM_ADDR_IO_BBL 0x8000e000 +#define MM_ADDR_IO_OTP 0x8000f000 +#define MM_ADDR_IO_I2S0 0x80010000 +#define MM_ADDR_IO_I2S1 0x80011000 +#define MM_ADDR_IO_UARTA 0x80012000 +#define MM_ADDR_IO_UARTB 0x80013000 +#define MM_ADDR_IO_I2CH 0x80014020 +#define MM_ADDR_IO_SPIH 0x80015000 +#define MM_ADDR_IO_TSC 0x80016000 +#define MM_ADDR_IO_TMR 0x80017000 +#define MM_ADDR_IO_WATCHDOG 0x80017800 +#define MM_ADDR_IO_ETM 0x80018000 +#define MM_ADDR_IO_DDRC 0x80019000 +#define MM_ADDR_IO_SINTC 0x80100000 +#define MM_ADDR_IO_INTC0 0x80200000 +#define MM_ADDR_IO_INTC1 0x80201000 +#define MM_ADDR_IO_GE 0x80300000 +#define MM_ADDR_IO_USB_CTLR0 0x80400000 +#define MM_ADDR_IO_USB_CTLR1 0x80410000 +#define MM_ADDR_IO_USB_PHY 0x80420000 +#define MM_ADDR_IO_SDIOH0 0x80500000 +#define MM_ADDR_IO_SDIOH1 0x80600000 +#define MM_ADDR_IO_VDEC 0x80700000 + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +#endif /* _MM_ADDR_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/mm_io.h b/arch/arm/mach-bcmring/include/mach/csp/mm_io.h new file mode 100644 index 0000000000000..de92ec6a01aa4 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/mm_io.h @@ -0,0 +1,147 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file mm_io.h +* +* @brief Memory Map I/O definitions +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef _MM_IO_H +#define _MM_IO_H + +/* ---- Include Files ---------------------------------------------------- */ +#include <mach/csp/mm_addr.h> + +#if !defined(CSP_SIMULATION) +#include <cfg_global.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ + +#if defined(CONFIG_MMU) + +/* This macro is referenced in <mach/io.h> + * Phys to Virtual 0xNyxxxxxx => 0xFNxxxxxx + * This macro is referenced in <asm/arch/io.h> + * + * Assume VPM address is the last x MB of memory. For VPM, map to + * 0xf0000000 and up. + */ + +#ifndef MM_IO_PHYS_TO_VIRT +#ifdef __ASSEMBLY__ +#define MM_IO_PHYS_TO_VIRT(phys) (0xF0000000 | (((phys) >> 4) & 0x0F000000) | ((phys) & 0xFFFFFF)) +#else +#define MM_IO_PHYS_TO_VIRT(phys) (((phys) == MM_ADDR_IO_VPM_EXTMEM_RSVD) ? 0xF0000000 : \ + (0xF0000000 | (((phys) >> 4) & 0x0F000000) | ((phys) & 0xFFFFFF))) +#endif +#endif + +/* Virtual to Physical 0xFNxxxxxx => 0xN0xxxxxx */ + +#ifndef MM_IO_VIRT_TO_PHYS +#ifdef __ASSEMBLY__ +#define MM_IO_VIRT_TO_PHYS(virt) ((((virt) & 0x0F000000) << 4) | ((virt) & 0xFFFFFF)) +#else +#define MM_IO_VIRT_TO_PHYS(virt) (((virt) == 0xF0000000) ? MM_ADDR_IO_VPM_EXTMEM_RSVD : \ + ((((virt) & 0x0F000000) << 4) | ((virt) & 0xFFFFFF))) +#endif +#endif + +#else + +#ifndef MM_IO_PHYS_TO_VIRT +#define MM_IO_PHYS_TO_VIRT(phys) (phys) +#endif + +#ifndef MM_IO_VIRT_TO_PHYS +#define MM_IO_VIRT_TO_PHYS(virt) (virt) +#endif + +#endif + +/* Registers in 0xExxxxxxx that should be moved to 0xFxxxxxxx */ +#define MM_IO_BASE_FLASHC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_FLASHC) +#define MM_IO_BASE_NAND MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_NAND) +#define MM_IO_BASE_UMI MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_UMI) + +#define MM_IO_START MM_ADDR_IO_FLASHC /* Physical beginning of IO mapped memory */ +#define MM_IO_BASE MM_IO_BASE_FLASHC /* Virtual beginning of IO mapped memory */ + +#define MM_IO_BASE_BROM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_BROM) +#define MM_IO_BASE_ARAM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_ARAM) +#define MM_IO_BASE_DMA0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_DMA0) +#define MM_IO_BASE_DMA1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_DMA1) +#define MM_IO_BASE_ESW MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_ESW) +#define MM_IO_BASE_CLCD MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_CLCD) +#define MM_IO_BASE_PIF MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_PIF) +#define MM_IO_BASE_APM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_APM) +#define MM_IO_BASE_SPUM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SPUM) +#define MM_IO_BASE_VPM_PROG MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VPM_PROG) +#define MM_IO_BASE_VPM_DATA MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VPM_DATA) + +#define MM_IO_BASE_VRAM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VRAM) + +#define MM_IO_BASE_CHIPC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_CHIPC) +#define MM_IO_BASE_DDRC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_DDRC) +#define MM_IO_BASE_LEDM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_LEDM) +#define MM_IO_BASE_PWM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_PWM) +#define MM_IO_BASE_VINTC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VINTC) +#define MM_IO_BASE_GPIO0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_GPIO0) +#define MM_IO_BASE_GPIO1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_GPIO1) +#define MM_IO_BASE_TMR MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_TMR) +#define MM_IO_BASE_WATCHDOG MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_WATCHDOG) +#define MM_IO_BASE_ETM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_ETM) +#define MM_IO_BASE_HPM MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_HPM) +#define MM_IO_BASE_HPM_REMAP MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_HPM_REMAP) +#define MM_IO_BASE_TZPC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_TZPC) +#define MM_IO_BASE_MPU MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_MPU) +#define MM_IO_BASE_SPUMP MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SPUMP) +#define MM_IO_BASE_PKA MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_PKA) +#define MM_IO_BASE_RNG MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_RNG) +#define MM_IO_BASE_KEYC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_KEYC) +#define MM_IO_BASE_BBL MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_BBL) +#define MM_IO_BASE_OTP MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_OTP) +#define MM_IO_BASE_I2S0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_I2S0) +#define MM_IO_BASE_I2S1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_I2S1) +#define MM_IO_BASE_UARTA MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_UARTA) +#define MM_IO_BASE_UARTB MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_UARTB) +#define MM_IO_BASE_I2CH MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_I2CH) +#define MM_IO_BASE_SPIH MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SPIH) +#define MM_IO_BASE_TSC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_TSC) +#define MM_IO_BASE_I2CS MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_I2CS) +#define MM_IO_BASE_SPIS MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SPIS) +#define MM_IO_BASE_SINTC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SINTC) +#define MM_IO_BASE_INTC0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_INTC0) +#define MM_IO_BASE_INTC1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_INTC1) +#define MM_IO_BASE_GE MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_GE) +#define MM_IO_BASE_USB_CTLR0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_USB_CTLR0) +#define MM_IO_BASE_USB_CTLR1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_USB_CTLR1) +#define MM_IO_BASE_USB_PHY MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_USB_PHY) +#define MM_IO_BASE_SDIOH0 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SDIOH0) +#define MM_IO_BASE_SDIOH1 MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_SDIOH1) +#define MM_IO_BASE_VDEC MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VDEC) + +#define MM_IO_BASE_VPM_EXTMEM_RSVD MM_IO_PHYS_TO_VIRT(MM_ADDR_IO_VPM_EXTMEM_RSVD) + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +#endif /* _MM_IO_H */ diff --git a/arch/arm/mach-bcmring/include/mach/memory.h b/arch/arm/mach-bcmring/include/mach/memory.h new file mode 100644 index 0000000000000..114f942bb4f32 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/memory.h @@ -0,0 +1,33 @@ +/***************************************************************************** +* Copyright 2005 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#include <cfg_global.h> + +/* + * Physical vs virtual RAM address space conversion. These are + * private definitions which should NOT be used outside memory.h + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. + */ + +#define PHYS_OFFSET CFG_GLOBAL_RAM_BASE + +/* + * Maximum DMA memory allowed is 14M + */ +#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M) + +#endif diff --git a/arch/arm/mach-bcmring/include/mach/memory_settings.h b/arch/arm/mach-bcmring/include/mach/memory_settings.h new file mode 100644 index 0000000000000..ce5cd16f2ac4a --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/memory_settings.h @@ -0,0 +1,67 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef MEMORY_SETTINGS_H +#define MEMORY_SETTINGS_H + +/* ---- Include Files ---------------------------------------- */ +/* ---- Constants and Types ---------------------------------- */ + +/* Memory devices */ +/* NAND Flash timing for 166 MHz setting */ +#define HW_CFG_NAND_tBTA (5 << 16) /* Bus turnaround cycle (n) 0-7 (30 ns) */ +#define HW_CFG_NAND_tWP (4 << 11) /* Write pulse width cycle (n+1) 0-31 (25 ns) */ +#define HW_CFG_NAND_tWR (1 << 9) /* Write recovery cycle (n+1) 0-3 (10 ns) */ +#define HW_CFG_NAND_tAS (0 << 7) /* Write address setup cycle (n+1) 0-3 ( 0 ns) */ +#define HW_CFG_NAND_tOE (3 << 5) /* Output enable delay cycle (n) 0-3 (15 ns) */ +#define HW_CFG_NAND_tRC (7 << 0) /* Read access cycle (n+2) 0-31 (50 ns) */ + +#define HW_CFG_NAND_TCR (HW_CFG_NAND_tBTA \ + | HW_CFG_NAND_tWP \ + | HW_CFG_NAND_tWR \ + | HW_CFG_NAND_tAS \ + | HW_CFG_NAND_tOE \ + | HW_CFG_NAND_tRC) + +/* NOR Flash timing for 166 MHz setting */ +#define HW_CFG_NOR_TPRC_TWLC (0 << 19) /* Page read access cycle / Burst write latency (n+2 / n+1) (max 25ns) */ +#define HW_CFG_NOR_TBTA (0 << 16) /* Bus turnaround cycle (n) (DNA) */ +#define HW_CFG_NOR_TWP (6 << 11) /* Write pulse width cycle (n+1) (35ns) */ +#define HW_CFG_NOR_TWR (0 << 9) /* Write recovery cycle (n+1) (0ns) */ +#define HW_CFG_NOR_TAS (0 << 7) /* Write address setup cycle (n+1) (0ns) */ +#define HW_CFG_NOR_TOE (0 << 5) /* Output enable delay cycle (n) (max 25ns) */ +#define HW_CFG_NOR_TRC_TLC (0x10 << 0) /* Read access cycle / Burst read latency (n+2 / n+1) (100ns) */ + +#define HW_CFG_FLASH0_TCR (HW_CFG_NOR_TPRC_TWLC \ + | HW_CFG_NOR_TBTA \ + | HW_CFG_NOR_TWP \ + | HW_CFG_NOR_TWR \ + | HW_CFG_NOR_TAS \ + | HW_CFG_NOR_TOE \ + | HW_CFG_NOR_TRC_TLC) + +#define HW_CFG_FLASH1_TCR HW_CFG_FLASH0_TCR +#define HW_CFG_FLASH2_TCR HW_CFG_FLASH0_TCR + +/* SDRAM Settings */ +/* #define HW_CFG_SDRAM_CAS_LATENCY 5 Default 5, Values [3..6] */ +/* #define HW_CFG_SDRAM_CHIP_SELECT_CNT 1 Default 1, Vaules [1..2] */ +/* #define HW_CFG_SDRAM_SPEED_GRADE 667 Default 667, Values [400,533,667,800] */ +/* #define HW_CFG_SDRAM_WIDTH_BITS 16 Default 16, Vaules [8,16] */ +#define HW_CFG_SDRAM_SIZE_BYTES 0x10000000 /* Total memory, not per device size */ + +/* ---- Variable Externs ------------------------------------- */ +/* ---- Function Prototypes ---------------------------------- */ + +#endif /* MEMORY_SETTINGS_H */ diff --git a/arch/arm/mach-bcmring/include/mach/vmalloc.h b/arch/arm/mach-bcmring/include/mach/vmalloc.h new file mode 100644 index 0000000000000..35e2ead8395c5 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/vmalloc.h @@ -0,0 +1,25 @@ +/* + * + * Copyright (C) 2000 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Move VMALLOC_END to 0xf0000000 so that the vm space can range from + * 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles + * larger physical memory designs better. + */ +#define VMALLOC_END (PAGE_OFFSET + 0x30000000) diff --git a/arch/arm/mach-bcmring/mm.c b/arch/arm/mach-bcmring/mm.c new file mode 100644 index 0000000000000..0f1c37e4523ae --- /dev/null +++ b/arch/arm/mach-bcmring/mm.c @@ -0,0 +1,56 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include <linux/platform_device.h> +#include <asm/mach/map.h> + +#include <mach/hardware.h> +#include <mach/csp/mm_io.h> + +#define IO_DESC(va, sz) { .virtual = va, \ + .pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \ + .length = sz, \ + .type = MT_DEVICE } + +#define MEM_DESC(va, sz) { .virtual = va, \ + .pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \ + .length = sz, \ + .type = MT_MEMORY } + +static struct map_desc bcmring_io_desc[] __initdata = { + IO_DESC(MM_IO_BASE_NAND, SZ_64K), /* phys:0x28000000-0x28000FFF virt:0xE8000000-0xE8000FFF size:0x00010000 */ + IO_DESC(MM_IO_BASE_UMI, SZ_64K), /* phys:0x2C000000-0x2C000FFF virt:0xEC000000-0xEC000FFF size:0x00010000 */ + + IO_DESC(MM_IO_BASE_BROM, SZ_64K), /* phys:0x30000000-0x3000FFFF virt:0xF3000000-0xF300FFFF size:0x00010000 */ + MEM_DESC(MM_IO_BASE_ARAM, SZ_1M), /* phys:0x31000000-0x31FFFFFF virt:0xF3100000-0xF31FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_DMA0, SZ_1M), /* phys:0x32000000-0x32FFFFFF virt:0xF3200000-0xF32FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_DMA1, SZ_1M), /* phys:0x33000000-0x33FFFFFF virt:0xF3300000-0xF33FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_ESW, SZ_1M), /* phys:0x34000000-0x34FFFFFF virt:0xF3400000-0xF34FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_CLCD, SZ_1M), /* phys:0x35000000-0x35FFFFFF virt:0xF3500000-0xF35FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_APM, SZ_1M), /* phys:0x36000000-0x36FFFFFF virt:0xF3600000-0xF36FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_SPUM, SZ_1M), /* phys:0x37000000-0x37FFFFFF virt:0xF3700000-0xF37FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_VPM_PROG, SZ_1M), /* phys:0x38000000-0x38FFFFFF virt:0xF3800000-0xF38FFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_VPM_DATA, SZ_1M), /* phys:0x3A000000-0x3AFFFFFF virt:0xF3A00000-0xF3AFFFFF size:0x01000000 */ + + IO_DESC(MM_IO_BASE_VRAM, SZ_64K), /* phys:0x40000000-0x4000FFFF virt:0xF4000000-0xF400FFFF size:0x00010000 */ + IO_DESC(MM_IO_BASE_CHIPC, SZ_16M), /* phys:0x80000000-0x80FFFFFF virt:0xF8000000-0xF8FFFFFF size:0x01000000 */ + IO_DESC(MM_IO_BASE_VPM_EXTMEM_RSVD, + SZ_16M), /* phys:0x0F000000-0x0FFFFFFF virt:0xF0000000-0xF0FFFFFF size:0x01000000 */ +}; + +void __init bcmring_map_io(void) +{ + + iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc)); +} -- GitLab From 7c4c2951c0077eecf9a9dfda59a43eedd09a01f4 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:00:39 +0100 Subject: [PATCH 0977/1002] ARM: 5647/1: bcmring: add bcmring dma.h and dma_device.c add bcmring dma.h and dma_device.c Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/dma_device.c | 593 ++++++++++++++++ arch/arm/mach-bcmring/include/mach/dma.h | 826 +++++++++++++++++++++++ 2 files changed, 1419 insertions(+) create mode 100644 arch/arm/mach-bcmring/dma_device.c create mode 100644 arch/arm/mach-bcmring/include/mach/dma.h diff --git a/arch/arm/mach-bcmring/dma_device.c b/arch/arm/mach-bcmring/dma_device.c new file mode 100644 index 0000000000000..ca0ad736870bb --- /dev/null +++ b/arch/arm/mach-bcmring/dma_device.c @@ -0,0 +1,593 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dma_device.c +* +* @brief private array of DMA_DeviceAttribute_t +*/ +/****************************************************************************/ + +DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES] = { + [DMA_DEVICE_MEM_TO_MEM] = /* MEM 2 MEM */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "mem-to-mem", + .config = { + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + + }, + }, + [DMA_DEVICE_VPM_MEM_TO_MEM] = /* VPM */ + { + .flags = DMA_DEVICE_FLAG_IS_DEDICATED | DMA_DEVICE_FLAG_NO_ISR, + .name = "vpm", + .dedicatedController = 0, + .dedicatedChannel = 0, + /* reserve DMA0:0 for VPM */ + }, + [DMA_DEVICE_NAND_MEM_TO_MEM] = /* NAND */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "nand", + .config = { + .srcPeripheralPort = 0, + .dstPeripheralPort = 0, + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_6, + }, + }, + [DMA_DEVICE_PIF_MEM_TO_DEV] = /* PIF TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1 + | DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO + | DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST | DMA_DEVICE_FLAG_PORT_PER_DMAC, + .name = "pif_tx", + .dmacPort = {14, 5}, + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + /* dstPeripheralPort = 5 or 14 */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + .maxDataPerBlock = 16256, + }, + }, + [DMA_DEVICE_PIF_DEV_TO_MEM] = /* PIF RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1 + | DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO + /* DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST */ + | DMA_DEVICE_FLAG_PORT_PER_DMAC, + .name = "pif_rx", + .dmacPort = {14, 5}, + .config = { + /* srcPeripheralPort = 5 or 14 */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + .maxDataPerBlock = 16256, + }, + }, + [DMA_DEVICE_I2S0_DEV_TO_MEM] = /* I2S RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "i2s0_rx", + .config = { + .srcPeripheralPort = 0, /* SRC: I2S0 */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_16, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_I2S0_MEM_TO_DEV] = /* I2S TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "i2s0_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 1, /* DST: I2S0 */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_16, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_I2S1_DEV_TO_MEM] = /* I2S1 RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA1, + .name = "i2s1_rx", + .config = { + .srcPeripheralPort = 2, /* SRC: I2S1 */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_16, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_I2S1_MEM_TO_DEV] = /* I2S1 TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA1, + .name = "i2s1_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 3, /* DST: I2S1 */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_16, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_ESW_MEM_TO_DEV] = /* ESW TX */ + { + .name = "esw_tx", + .flags = DMA_DEVICE_FLAG_IS_DEDICATED, + .dedicatedController = 1, + .dedicatedChannel = 3, + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 1, /* DST: ESW (MTP) */ + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_DISABLE, + /* DMAx_AHB_SSTATARy */ + .srcStatusRegisterAddress = 0x00000000, + /* DMAx_AHB_DSTATARy */ + .dstStatusRegisterAddress = 0x30490010, + /* DMAx_AHB_CFGy */ + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + /* DMAx_AHB_CTLy */ + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + }, + }, + [DMA_DEVICE_ESW_DEV_TO_MEM] = /* ESW RX */ + { + .name = "esw_rx", + .flags = DMA_DEVICE_FLAG_IS_DEDICATED, + .dedicatedController = 1, + .dedicatedChannel = 2, + .config = { + .srcPeripheralPort = 0, /* SRC: ESW (PTM) */ + .dstPeripheralPort = 0, /* DST: memory */ + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_DISABLE, + /* DMAx_AHB_SSTATARy */ + .srcStatusRegisterAddress = 0x30480010, + /* DMAx_AHB_DSTATARy */ + .dstStatusRegisterAddress = 0x00000000, + /* DMAx_AHB_CFGy */ + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + /* DMAx_AHB_CTLy */ + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + }, + }, + [DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM] = /* APM Codec A Ingress */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "apm_a_rx", + .config = { + .srcPeripheralPort = 2, /* SRC: Codec A Ingress FIFO */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV] = /* APM Codec A Egress */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "apm_a_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 3, /* DST: Codec A Egress FIFO */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM] = /* APM Codec B Ingress */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "apm_b_rx", + .config = { + .srcPeripheralPort = 4, /* SRC: Codec B Ingress FIFO */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV] = /* APM Codec B Egress */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "apm_b_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 5, /* DST: Codec B Egress FIFO */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM] = /* APM Codec C Ingress */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA1, + .name = "apm_c_rx", + .config = { + .srcPeripheralPort = 4, /* SRC: Codec C Ingress FIFO */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_APM_PCM0_DEV_TO_MEM] = /* PCM0 RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "pcm0_rx", + .config = { + .srcPeripheralPort = 12, /* SRC: PCM0 */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_APM_PCM0_MEM_TO_DEV] = /* PCM0 TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0, + .name = "pcm0_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 13, /* DST: PCM0 */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_APM_PCM1_DEV_TO_MEM] = /* PCM1 RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA1, + .name = "pcm1_rx", + .config = { + .srcPeripheralPort = 14, /* SRC: PCM1 */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4, + .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS, + }, + }, + [DMA_DEVICE_APM_PCM1_MEM_TO_DEV] = /* PCM1 TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA1, + .name = "pcm1_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 15, /* DST: PCM1 */ + .srcStatusRegisterAddress = 0, + .dstStatusRegisterAddress = 0, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_SPUM_DEV_TO_MEM] = /* SPUM RX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "spum_rx", + .config = { + .srcPeripheralPort = 6, /* SRC: Codec A Ingress FIFO */ + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + /* Busrt size **MUST** be 16 for SPUM to work */ + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_16, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_16, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + /* on the RX side, SPU needs to be the flow controller */ + .flowControler = dmacHw_FLOW_CONTROL_PERIPHERAL, + }, + }, + [DMA_DEVICE_SPUM_MEM_TO_DEV] = /* SPUM TX */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "spum_tx", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .dstPeripheralPort = 7, /* DST: SPUM */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32, + /* Busrt size **MUST** be 16 for SPUM to work */ + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_16, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_16, + .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST, + }, + }, + [DMA_DEVICE_MEM_TO_VRAM] = /* MEM 2 VRAM */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "mem-to-vram", + .config = { + .srcPeripheralPort = 0, /* SRC: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + }, + }, + [DMA_DEVICE_VRAM_TO_MEM] = /* VRAM 2 MEM */ + { + .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1, + .name = "vram-to-mem", + .config = { + .dstPeripheralPort = 0, /* DST: memory */ + .srcStatusRegisterAddress = 0x00000000, + .dstStatusRegisterAddress = 0x00000000, + .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC, + .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC, + .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM, + .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2, + .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1, + .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE, + .errorInterrupt = dmacHw_INTERRUPT_ENABLE, + .channelPriority = dmacHw_CHANNEL_PRIORITY_7, + .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64, + .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64, + .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8, + .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8, + }, + }, +}; +EXPORT_SYMBOL(DMA_gDeviceAttribute); /* primarily for dma-test.c */ diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h new file mode 100644 index 0000000000000..847980c85c88f --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/dma.h @@ -0,0 +1,826 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dma.h +* +* @brief API definitions for the linux DMA interface. +*/ +/****************************************************************************/ + +#if !defined(ASM_ARM_ARCH_BCMRING_DMA_H) +#define ASM_ARM_ARCH_BCMRING_DMA_H + +/* ---- Include Files ---------------------------------------------------- */ + +#include <linux/kernel.h> +#include <linux/wait.h> +#include <linux/semaphore.h> +#include <csp/dmacHw.h> +#include <mach/timer.h> +#include <linux/scatterlist.h> +#include <linux/dma-mapping.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/pagemap.h> + +/* ---- Constants and Types ---------------------------------------------- */ + +/* If DMA_DEBUG_TRACK_RESERVATION is set to a non-zero value, then the filename */ +/* and line number of the reservation request will be recorded in the channel table */ + +#define DMA_DEBUG_TRACK_RESERVATION 1 + +#define DMA_NUM_CONTROLLERS 2 +#define DMA_NUM_CHANNELS 8 /* per controller */ + +typedef enum { + DMA_DEVICE_MEM_TO_MEM, /* For memory to memory transfers */ + DMA_DEVICE_I2S0_DEV_TO_MEM, + DMA_DEVICE_I2S0_MEM_TO_DEV, + DMA_DEVICE_I2S1_DEV_TO_MEM, + DMA_DEVICE_I2S1_MEM_TO_DEV, + DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM, + DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV, + DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM, + DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV, + DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM, /* Additional mic input for beam-forming */ + DMA_DEVICE_APM_PCM0_DEV_TO_MEM, + DMA_DEVICE_APM_PCM0_MEM_TO_DEV, + DMA_DEVICE_APM_PCM1_DEV_TO_MEM, + DMA_DEVICE_APM_PCM1_MEM_TO_DEV, + DMA_DEVICE_SPUM_DEV_TO_MEM, + DMA_DEVICE_SPUM_MEM_TO_DEV, + DMA_DEVICE_SPIH_DEV_TO_MEM, + DMA_DEVICE_SPIH_MEM_TO_DEV, + DMA_DEVICE_UART_A_DEV_TO_MEM, + DMA_DEVICE_UART_A_MEM_TO_DEV, + DMA_DEVICE_UART_B_DEV_TO_MEM, + DMA_DEVICE_UART_B_MEM_TO_DEV, + DMA_DEVICE_PIF_MEM_TO_DEV, + DMA_DEVICE_PIF_DEV_TO_MEM, + DMA_DEVICE_ESW_DEV_TO_MEM, + DMA_DEVICE_ESW_MEM_TO_DEV, + DMA_DEVICE_VPM_MEM_TO_MEM, + DMA_DEVICE_CLCD_MEM_TO_MEM, + DMA_DEVICE_NAND_MEM_TO_MEM, + DMA_DEVICE_MEM_TO_VRAM, + DMA_DEVICE_VRAM_TO_MEM, + + /* Add new entries before this line. */ + + DMA_NUM_DEVICE_ENTRIES, + DMA_DEVICE_NONE = 0xff, /* Special value to indicate that no device is currently assigned. */ + +} DMA_Device_t; + +/**************************************************************************** +* +* The DMA_Handle_t is the primary object used by callers of the API. +* +*****************************************************************************/ + +#define DMA_INVALID_HANDLE ((DMA_Handle_t) -1) + +typedef int DMA_Handle_t; + +/**************************************************************************** +* +* The DMA_DescriptorRing_t contains a ring of descriptors which is used +* to point to regions of memory. +* +*****************************************************************************/ + +typedef struct { + void *virtAddr; /* Virtual Address of the descriptor ring */ + dma_addr_t physAddr; /* Physical address of the descriptor ring */ + int descriptorsAllocated; /* Number of descriptors allocated in the descriptor ring */ + size_t bytesAllocated; /* Number of bytes allocated in the descriptor ring */ + +} DMA_DescriptorRing_t; + +/**************************************************************************** +* +* The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup +* DMA chains from a variety of memory sources. +* +*****************************************************************************/ + +#define DMA_MEM_MAP_MIN_SIZE 4096 /* Pages less than this size are better */ + /* off not being DMA'd. */ + +typedef enum { + DMA_MEM_TYPE_NONE, /* Not a valid setting */ + DMA_MEM_TYPE_VMALLOC, /* Memory came from vmalloc call */ + DMA_MEM_TYPE_KMALLOC, /* Memory came from kmalloc call */ + DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */ + DMA_MEM_TYPE_USER, /* Memory came from user space. */ + +} DMA_MemType_t; + +/* A segment represents a physically and virtually contiguous chunk of memory. */ +/* i.e. each segment can be DMA'd */ +/* A user of the DMA code will add memory regions. Each region may need to be */ +/* represented by one or more segments. */ + +typedef struct { + void *virtAddr; /* Virtual address used for this segment */ + dma_addr_t physAddr; /* Physical address this segment maps to */ + size_t numBytes; /* Size of the segment, in bytes */ + +} DMA_Segment_t; + +/* A region represents a virtually contiguous chunk of memory, which may be */ +/* made up of multiple segments. */ + +typedef struct { + DMA_MemType_t memType; + void *virtAddr; + size_t numBytes; + + /* Each region (virtually contiguous) consists of one or more segments. Each */ + /* segment is virtually and physically contiguous. */ + + int numSegmentsUsed; + int numSegmentsAllocated; + DMA_Segment_t *segment; + + /* When a region corresponds to user memory, we need to lock all of the pages */ + /* down before we can figure out the physical addresses. The lockedPage array contains */ + /* the pages that were locked, and which subsequently need to be unlocked once the */ + /* memory is unmapped. */ + + unsigned numLockedPages; + struct page **lockedPages; + +} DMA_Region_t; + +typedef struct { + int inUse; /* Is this mapping currently being used? */ + struct semaphore lock; /* Acquired when using this structure */ + enum dma_data_direction dir; /* Direction this transfer is intended for */ + + /* In the event that we're mapping user memory, we need to know which task */ + /* the memory is for, so that we can obtain the correct mm locks. */ + + struct task_struct *userTask; + + int numRegionsUsed; + int numRegionsAllocated; + DMA_Region_t *region; + +} DMA_MemMap_t; + +/**************************************************************************** +* +* The DMA_DeviceAttribute_t contains information which describes a +* particular DMA device (or peripheral). +* +* It is anticipated that the arrary of DMA_DeviceAttribute_t's will be +* statically initialized. +* +*****************************************************************************/ + +/* The device handler is called whenever a DMA operation completes. The reaon */ +/* for it to be called will be a bitmask with one or more of the following bits */ +/* set. */ + +#define DMA_HANDLER_REASON_BLOCK_COMPLETE dmacHw_INTERRUPT_STATUS_BLOCK +#define DMA_HANDLER_REASON_TRANSFER_COMPLETE dmacHw_INTERRUPT_STATUS_TRANS +#define DMA_HANDLER_REASON_ERROR dmacHw_INTERRUPT_STATUS_ERROR + +typedef void (*DMA_DeviceHandler_t) (DMA_Device_t dev, int reason, + void *userData); + +#define DMA_DEVICE_FLAG_ON_DMA0 0x00000001 +#define DMA_DEVICE_FLAG_ON_DMA1 0x00000002 +#define DMA_DEVICE_FLAG_PORT_PER_DMAC 0x00000004 /* If set, it means that the port used on DMAC0 is different from the port used on DMAC1 */ +#define DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST 0x00000008 /* If set, allocate from DMA1 before allocating from DMA0 */ +#define DMA_DEVICE_FLAG_IS_DEDICATED 0x00000100 +#define DMA_DEVICE_FLAG_NO_ISR 0x00000200 +#define DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO 0x00000400 +#define DMA_DEVICE_FLAG_IN_USE 0x00000800 /* If set, device is in use on a channel */ + +/* Note: Some DMA devices can be used from multiple DMA Controllers. The bitmask is used to */ +/* determine which DMA controllers a given device can be used from, and the interface */ +/* array determeines the actual interface number to use for a given controller. */ + +typedef struct { + uint32_t flags; /* Bitmask of DMA_DEVICE_FLAG_xxx constants */ + uint8_t dedicatedController; /* Controller number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */ + uint8_t dedicatedChannel; /* Channel number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */ + const char *name; /* Will show up in the /proc entry */ + + uint32_t dmacPort[DMA_NUM_CONTROLLERS]; /* Specifies the port number when DMA_DEVICE_FLAG_PORT_PER_DMAC flag is set */ + + dmacHw_CONFIG_t config; /* Configuration to use when DMA'ing using this device */ + + void *userData; /* Passed to the devHandler */ + DMA_DeviceHandler_t devHandler; /* Called when DMA operations finish. */ + + timer_tick_count_t transferStartTime; /* Time the current transfer was started */ + + /* The following statistical information will be collected and presented in a proc entry. */ + /* Note: With a contiuous bandwidth of 1 Gb/sec, it would take 584 years to overflow */ + /* a 64 bit counter. */ + + uint64_t numTransfers; /* Number of DMA transfers performed */ + uint64_t transferTicks; /* Total time spent doing DMA transfers (measured in timer_tick_count_t's) */ + uint64_t transferBytes; /* Total bytes transferred */ + uint32_t timesBlocked; /* Number of times a channel was unavailable */ + uint32_t numBytes; /* Last transfer size */ + + /* It's not possible to free memory which is allocated for the descriptors from within */ + /* the ISR. So make the presumption that a given device will tend to use the */ + /* same sized buffers over and over again, and we keep them around. */ + + DMA_DescriptorRing_t ring; /* Ring of descriptors allocated for this device */ + + /* We stash away some of the information from the previous transfer. If back-to-back */ + /* transfers are performed from the same buffer, then we don't have to keep re-initializing */ + /* the descriptor buffers. */ + + uint32_t prevNumBytes; + dma_addr_t prevSrcData; + dma_addr_t prevDstData; + +} DMA_DeviceAttribute_t; + +/**************************************************************************** +* +* DMA_Channel_t, DMA_Controller_t, and DMA_State_t are really internal +* data structures and don't belong in this header file, but are included +* merely for discussion. +* +* By the time this is implemented, these structures will be moved out into +* the appropriate C source file instead. +* +*****************************************************************************/ + +/**************************************************************************** +* +* The DMA_Channel_t contains state information about each DMA channel. Some +* of the channels are dedicated. Non-dedicated channels are shared +* amongst the other devices. +* +*****************************************************************************/ + +#define DMA_CHANNEL_FLAG_IN_USE 0x00000001 +#define DMA_CHANNEL_FLAG_IS_DEDICATED 0x00000002 +#define DMA_CHANNEL_FLAG_NO_ISR 0x00000004 +#define DMA_CHANNEL_FLAG_LARGE_FIFO 0x00000008 + +typedef struct { + uint32_t flags; /* bitmask of DMA_CHANNEL_FLAG_xxx constants */ + DMA_Device_t devType; /* Device this channel is currently reserved for */ + DMA_Device_t lastDevType; /* Device type that used this previously */ + char name[20]; /* Name passed onto request_irq */ + +#if (DMA_DEBUG_TRACK_RESERVATION) + const char *fileName; /* Place where channel reservation took place */ + int lineNum; /* Place where channel reservation took place */ +#endif + dmacHw_HANDLE_t dmacHwHandle; /* low level channel handle. */ + +} DMA_Channel_t; + +/**************************************************************************** +* +* The DMA_Controller_t contains state information about each DMA controller. +* +* The freeChannelQ is stored in the controller data structure rather than +* the channel data structure since several of the devices are accessible +* from multiple controllers, and there is no way to know which controller +* will become available first. +* +*****************************************************************************/ + +typedef struct { + DMA_Channel_t channel[DMA_NUM_CHANNELS]; + +} DMA_Controller_t; + +/**************************************************************************** +* +* The DMA_Global_t contains all of the global state information used by +* the DMA code. +* +* Callers which need to allocate a shared channel will be queued up +* on the freeChannelQ until a channel becomes available. +* +*****************************************************************************/ + +typedef struct { + struct semaphore lock; /* acquired when manipulating table entries */ + wait_queue_head_t freeChannelQ; + + DMA_Controller_t controller[DMA_NUM_CONTROLLERS]; + +} DMA_Global_t; + +/* ---- Variable Externs ------------------------------------------------- */ + +extern DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES]; + +/* ---- Function Prototypes ---------------------------------------------- */ + +#if defined(__KERNEL__) + +/****************************************************************************/ +/** +* Initializes the DMA module. +* +* @return +* 0 - Success +* < 0 - Error +*/ +/****************************************************************************/ + +int dma_init(void); + +#if (DMA_DEBUG_TRACK_RESERVATION) +DMA_Handle_t dma_request_channel_dbg(DMA_Device_t dev, const char *fileName, + int lineNum); +#define dma_request_channel(dev) dma_request_channel_dbg(dev, __FILE__, __LINE__) +#else + +/****************************************************************************/ +/** +* Reserves a channel for use with @a dev. If the device is setup to use +* a shared channel, then this function will block until a free channel +* becomes available. +* +* @return +* >= 0 - A valid DMA Handle. +* -EBUSY - Device is currently being used. +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +DMA_Handle_t dma_request_channel(DMA_Device_t dev /* Device to use with the allocated channel. */ + ); +#endif + +/****************************************************************************/ +/** +* Frees a previously allocated DMA Handle. +* +* @return +* 0 - DMA Handle was released successfully. +* -EINVAL - Invalid DMA handle +*/ +/****************************************************************************/ + +int dma_free_channel(DMA_Handle_t channel /* DMA handle. */ + ); + +/****************************************************************************/ +/** +* Determines if a given device has been configured as using a shared +* channel. +* +* @return boolean +* 0 Device uses a dedicated channel +* non-zero Device uses a shared channel +*/ +/****************************************************************************/ + +int dma_device_is_channel_shared(DMA_Device_t dev /* Device to check. */ + ); + +/****************************************************************************/ +/** +* Allocates memory to hold a descriptor ring. The descriptor ring then +* needs to be populated by making one or more calls to +* dna_add_descriptors. +* +* The returned descriptor ring will be automatically initialized. +* +* @return +* 0 Descriptor ring was allocated successfully +* -ENOMEM Unable to allocate memory for the desired number of descriptors. +*/ +/****************************************************************************/ + +int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to populate */ + int numDescriptors /* Number of descriptors that need to be allocated. */ + ); + +/****************************************************************************/ +/** +* Releases the memory which was previously allocated for a descriptor ring. +*/ +/****************************************************************************/ + +void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring /* Descriptor to release */ + ); + +/****************************************************************************/ +/** +* Initializes a descriptor ring, so that descriptors can be added to it. +* Once a descriptor ring has been allocated, it may be reinitialized for +* use with additional/different regions of memory. +* +* Note that if 7 descriptors are allocated, it's perfectly acceptable to +* initialize the ring with a smaller number of descriptors. The amount +* of memory allocated for the descriptor ring will not be reduced, and +* the descriptor ring may be reinitialized later +* +* @return +* 0 Descriptor ring was initialized successfully +* -ENOMEM The descriptor which was passed in has insufficient space +* to hold the desired number of descriptors. +*/ +/****************************************************************************/ + +int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to initialize */ + int numDescriptors /* Number of descriptors to initialize. */ + ); + +/****************************************************************************/ +/** +* Determines the number of descriptors which would be required for a +* transfer of the indicated memory region. +* +* This function also needs to know which DMA device this transfer will +* be destined for, so that the appropriate DMA configuration can be retrieved. +* DMA parameters such as transfer width, and whether this is a memory-to-memory +* or memory-to-peripheral, etc can all affect the actual number of descriptors +* required. +* +* @return +* > 0 Returns the number of descriptors required for the indicated transfer +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_calculate_descriptor_count(DMA_Device_t device, /* DMA Device that this will be associated with */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ); + +/****************************************************************************/ +/** +* Adds a region of memory to the descriptor ring. Note that it may take +* multiple descriptors for each region of memory. It is the callers +* responsibility to allocate a sufficiently large descriptor ring. +* +* @return +* 0 Descriptors were added successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_add_descriptors(DMA_DescriptorRing_t *ring, /* Descriptor ring to add descriptors to */ + DMA_Device_t device, /* DMA Device that descriptors are for */ + dma_addr_t srcData, /* Place to get data (memory or device) */ + dma_addr_t dstData, /* Place to put data (memory or device) */ + size_t numBytes /* Number of bytes to transfer to the device */ + ); + +/****************************************************************************/ +/** +* Sets the descriptor ring associated with a device. +* +* Once set, the descriptor ring will be associated with the device, even +* across channel request/free calls. Passing in a NULL descriptor ring +* will release any descriptor ring currently associated with the device. +* +* Note: If you call dma_transfer, or one of the other dma_alloc_ functions +* the descriptor ring may be released and reallocated. +* +* Note: This function will release the descriptor memory for any current +* descriptor ring associated with this device. +*/ +/****************************************************************************/ + +int dma_set_device_descriptor_ring(DMA_Device_t device, /* Device to update the descriptor ring for. */ + DMA_DescriptorRing_t *ring /* Descriptor ring to add descriptors to */ + ); + +/****************************************************************************/ +/** +* Retrieves the descriptor ring associated with a device. +*/ +/****************************************************************************/ + +int dma_get_device_descriptor_ring(DMA_Device_t device, /* Device to retrieve the descriptor ring for. */ + DMA_DescriptorRing_t *ring /* Place to store retrieved ring */ + ); + +/****************************************************************************/ +/** +* Allocates buffers for the descriptors. This is normally done automatically +* but needs to be done explicitly when initiating a dma from interrupt +* context. +* +* @return +* 0 Descriptors were allocated successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_alloc_descriptors(DMA_Handle_t handle, /* DMA Handle */ + dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ); + +/****************************************************************************/ +/** +* Allocates and sets up descriptors for a double buffered circular buffer. +* +* This is primarily intended to be used for things like the ingress samples +* from a microphone. +* +* @return +* > 0 Number of descriptors actually allocated. +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */ + dma_addr_t srcData, /* Physical address of source data */ + dma_addr_t dstData1, /* Physical address of first destination buffer */ + dma_addr_t dstData2, /* Physical address of second destination buffer */ + size_t numBytes /* Number of bytes in each destination buffer */ + ); + +/****************************************************************************/ +/** +* Initializes a DMA_MemMap_t data structure +*/ +/****************************************************************************/ + +int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ + ); + +/****************************************************************************/ +/** +* Releases any memory currently being held by a memory mapping structure. +*/ +/****************************************************************************/ + +int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ + ); + +/****************************************************************************/ +/** +* Looks at a memory address and categorizes it. +* +* @return One of the values from the DMA_MemType_t enumeration. +*/ +/****************************************************************************/ + +DMA_MemType_t dma_mem_type(void *addr); + +/****************************************************************************/ +/** +* Sets the process (aka userTask) associated with a mem map. This is +* required if user-mode segments will be added to the mapping. +*/ +/****************************************************************************/ + +static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap, + struct task_struct *task) +{ + memMap->userTask = task; +} + +/****************************************************************************/ +/** +* Looks at a memory address and determines if we support DMA'ing to/from +* that type of memory. +* +* @return boolean - +* return value != 0 means dma supported +* return value == 0 means dma not supported +*/ +/****************************************************************************/ + +int dma_mem_supports_dma(void *addr); + +/****************************************************************************/ +/** +* Initializes a memory map for use. Since this function acquires a +* sempaphore within the memory map, it is VERY important that dma_unmap +* be called when you're finished using the map. +*/ +/****************************************************************************/ + +int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */ + enum dma_data_direction dir /* Direction that the mapping will be going */ + ); + +/****************************************************************************/ +/** +* Adds a segment of memory to a memory map. +* +* @return 0 on success, error code otherwise. +*/ +/****************************************************************************/ + +int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */ + void *mem, /* Virtual address that we want to get a map of */ + size_t numBytes /* Number of bytes being mapped */ + ); + +/****************************************************************************/ +/** +* Creates a descriptor ring from a memory mapping. +* +* @return 0 on sucess, error code otherwise. +*/ +/****************************************************************************/ + +int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */ + DMA_MemMap_t *memMap, /* Memory map that will be used */ + dma_addr_t devPhysAddr /* Physical address of device */ + ); + +/****************************************************************************/ +/** +* Maps in a memory region such that it can be used for performing a DMA. +* +* @return +*/ +/****************************************************************************/ + +int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */ + void *addr, /* Virtual address that we want to get a map of */ + size_t count, /* Number of bytes being mapped */ + enum dma_data_direction dir /* Direction that the mapping will be going */ + ); + +/****************************************************************************/ +/** +* Maps in a memory region such that it can be used for performing a DMA. +* +* @return +*/ +/****************************************************************************/ + +int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ + int dirtied /* non-zero if any of the pages were modified */ + ); + +/****************************************************************************/ +/** +* Initiates a transfer when the descriptors have already been setup. +* +* This is a special case, and normally, the dma_transfer_xxx functions should +* be used. +* +* @return +* 0 Transfer was started successfully +* -ENODEV Invalid handle +*/ +/****************************************************************************/ + +int dma_start_transfer(DMA_Handle_t handle); + +/****************************************************************************/ +/** +* Stops a previously started DMA transfer. +* +* @return +* 0 Transfer was stopped successfully +* -ENODEV Invalid handle +*/ +/****************************************************************************/ + +int dma_stop_transfer(DMA_Handle_t handle); + +/****************************************************************************/ +/** +* Waits for a DMA to complete by polling. This function is only intended +* to be used for testing. Interrupts should be used for most DMA operations. +*/ +/****************************************************************************/ + +int dma_wait_transfer_done(DMA_Handle_t handle); + +/****************************************************************************/ +/** +* Initiates a DMA transfer +* +* @return +* 0 Transfer was started successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +*/ +/****************************************************************************/ + +int dma_transfer(DMA_Handle_t handle, /* DMA Handle */ + dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ); + +/****************************************************************************/ +/** +* Initiates a transfer from memory to a device. +* +* @return +* 0 Transfer was started successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV) +*/ +/****************************************************************************/ + +static inline int dma_transfer_to_device(DMA_Handle_t handle, /* DMA Handle */ + dma_addr_t srcData, /* Place to get data to write to device (physical address) */ + dma_addr_t dstData, /* Pointer to device data address (physical address) */ + size_t numBytes /* Number of bytes to transfer to the device */ + ) { + return dma_transfer(handle, + dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, + srcData, dstData, numBytes); +} + +/****************************************************************************/ +/** +* Initiates a transfer from a device to memory. +* +* @return +* 0 Transfer was started successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +*/ +/****************************************************************************/ + +static inline int dma_transfer_from_device(DMA_Handle_t handle, /* DMA Handle */ + dma_addr_t srcData, /* Pointer to the device data address (physical address) */ + dma_addr_t dstData, /* Place to store data retrieved from the device (physical address) */ + size_t numBytes /* Number of bytes to retrieve from the device */ + ) { + return dma_transfer(handle, + dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, + srcData, dstData, numBytes); +} + +/****************************************************************************/ +/** +* Initiates a memory to memory transfer. +* +* @return +* 0 Transfer was started successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device wasn't DMA_DEVICE_MEM_TO_MEM) +*/ +/****************************************************************************/ + +static inline int dma_transfer_mem_to_mem(DMA_Handle_t handle, /* DMA Handle */ + dma_addr_t srcData, /* Place to transfer data from (physical address) */ + dma_addr_t dstData, /* Place to transfer data to (physical address) */ + size_t numBytes /* Number of bytes to transfer */ + ) { + return dma_transfer(handle, + dmacHw_TRANSFER_TYPE_MEM_TO_MEM, + srcData, dstData, numBytes); +} + +/****************************************************************************/ +/** +* Set the callback function which will be called when a transfer completes. +* If a NULL callback function is set, then no callback will occur. +* +* @note @a devHandler will be called from IRQ context. +* +* @return +* 0 - Success +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +int dma_set_device_handler(DMA_Device_t dev, /* Device to set the callback for. */ + DMA_DeviceHandler_t devHandler, /* Function to call when the DMA completes */ + void *userData /* Pointer which will be passed to devHandler. */ + ); + +#endif + +#endif /* ASM_ARM_ARCH_BCMRING_DMA_H */ -- GitLab From 859277f7dbf8b48016d55ea2171d04eed074d858 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:01:13 +0100 Subject: [PATCH 0978/1002] ARM: 5648/1: bcmring: add bmcring dma.c implement dma support for bcmring Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/dma.c | 2321 +++++++++++++++++++++++++++++++++++ 1 file changed, 2321 insertions(+) create mode 100644 arch/arm/mach-bcmring/dma.c diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c new file mode 100644 index 0000000000000..7b20fccb9d4ee --- /dev/null +++ b/arch/arm/mach-bcmring/dma.c @@ -0,0 +1,2321 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dma.c +* +* @brief Implements the DMA interface. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/irqreturn.h> +#include <linux/proc_fs.h> + +#include <mach/timer.h> + +#include <linux/mm.h> +#include <linux/pfn.h> +#include <asm/atomic.h> +#include <mach/dma.h> + +/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */ +/* especially since dc4 doesn't use kmalloc'd memory. */ + +#define ALLOW_MAP_OF_KMALLOC_MEMORY 0 + +/* ---- Public Variables ------------------------------------------------- */ + +/* ---- Private Constants and Types -------------------------------------- */ + +#define MAKE_HANDLE(controllerIdx, channelIdx) (((controllerIdx) << 4) | (channelIdx)) + +#define CONTROLLER_FROM_HANDLE(handle) (((handle) >> 4) & 0x0f) +#define CHANNEL_FROM_HANDLE(handle) ((handle) & 0x0f) + +#define DMA_MAP_DEBUG 0 + +#if DMA_MAP_DEBUG +# define DMA_MAP_PRINT(fmt, args...) printk("%s: " fmt, __func__, ## args) +#else +# define DMA_MAP_PRINT(fmt, args...) +#endif + +/* ---- Private Variables ------------------------------------------------ */ + +static DMA_Global_t gDMA; +static struct proc_dir_entry *gDmaDir; + +static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0); +static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0); +static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0); +static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0); + +#include "dma_device.c" + +/* ---- Private Function Prototypes -------------------------------------- */ + +/* ---- Functions ------------------------------------------------------- */ + +/****************************************************************************/ +/** +* Displays information for /proc/dma/mem-type +*/ +/****************************************************************************/ + +static int dma_proc_read_mem_type(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(buf + len, "dma_map_mem statistics\n"); + len += + sprintf(buf + len, "coherent: %d\n", + atomic_read(&gDmaStatMemTypeCoherent)); + len += + sprintf(buf + len, "kmalloc: %d\n", + atomic_read(&gDmaStatMemTypeKmalloc)); + len += + sprintf(buf + len, "vmalloc: %d\n", + atomic_read(&gDmaStatMemTypeVmalloc)); + len += + sprintf(buf + len, "user: %d\n", + atomic_read(&gDmaStatMemTypeUser)); + + return len; +} + +/****************************************************************************/ +/** +* Displays information for /proc/dma/channels +*/ +/****************************************************************************/ + +static int dma_proc_read_channels(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + int controllerIdx; + int channelIdx; + int limit = count - 200; + int len = 0; + DMA_Channel_t *channel; + + if (down_interruptible(&gDMA.lock) < 0) { + return -ERESTARTSYS; + } + + for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS; + controllerIdx++) { + for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; + channelIdx++) { + if (len >= limit) { + break; + } + + channel = + &gDMA.controller[controllerIdx].channel[channelIdx]; + + len += + sprintf(buf + len, "%d:%d ", controllerIdx, + channelIdx); + + if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) != + 0) { + len += + sprintf(buf + len, "Dedicated for %s ", + DMA_gDeviceAttribute[channel-> + devType].name); + } else { + len += sprintf(buf + len, "Shared "); + } + + if ((channel->flags & DMA_CHANNEL_FLAG_NO_ISR) != 0) { + len += sprintf(buf + len, "No ISR "); + } + + if ((channel->flags & DMA_CHANNEL_FLAG_LARGE_FIFO) != 0) { + len += sprintf(buf + len, "Fifo: 128 "); + } else { + len += sprintf(buf + len, "Fifo: 64 "); + } + + if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) { + len += + sprintf(buf + len, "InUse by %s", + DMA_gDeviceAttribute[channel-> + devType].name); +#if (DMA_DEBUG_TRACK_RESERVATION) + len += + sprintf(buf + len, " (%s:%d)", + channel->fileName, + channel->lineNum); +#endif + } else { + len += sprintf(buf + len, "Avail "); + } + + if (channel->lastDevType != DMA_DEVICE_NONE) { + len += + sprintf(buf + len, "Last use: %s ", + DMA_gDeviceAttribute[channel-> + lastDevType]. + name); + } + + len += sprintf(buf + len, "\n"); + } + } + up(&gDMA.lock); + *eof = 1; + + return len; +} + +/****************************************************************************/ +/** +* Displays information for /proc/dma/devices +*/ +/****************************************************************************/ + +static int dma_proc_read_devices(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + int limit = count - 200; + int len = 0; + int devIdx; + + if (down_interruptible(&gDMA.lock) < 0) { + return -ERESTARTSYS; + } + + for (devIdx = 0; devIdx < DMA_NUM_DEVICE_ENTRIES; devIdx++) { + DMA_DeviceAttribute_t *devAttr = &DMA_gDeviceAttribute[devIdx]; + + if (devAttr->name == NULL) { + continue; + } + + if (len >= limit) { + break; + } + + len += sprintf(buf + len, "%-12s ", devAttr->name); + + if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { + len += + sprintf(buf + len, "Dedicated %d:%d ", + devAttr->dedicatedController, + devAttr->dedicatedChannel); + } else { + len += sprintf(buf + len, "Shared DMA:"); + if ((devAttr->flags & DMA_DEVICE_FLAG_ON_DMA0) != 0) { + len += sprintf(buf + len, "0"); + } + if ((devAttr->flags & DMA_DEVICE_FLAG_ON_DMA1) != 0) { + len += sprintf(buf + len, "1"); + } + len += sprintf(buf + len, " "); + } + if ((devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) != 0) { + len += sprintf(buf + len, "NoISR "); + } + if ((devAttr->flags & DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO) != 0) { + len += sprintf(buf + len, "Allow-128 "); + } + + len += + sprintf(buf + len, + "Xfer #: %Lu Ticks: %Lu Bytes: %Lu DescLen: %u\n", + devAttr->numTransfers, devAttr->transferTicks, + devAttr->transferBytes, + devAttr->ring.bytesAllocated); + + } + + up(&gDMA.lock); + *eof = 1; + + return len; +} + +/****************************************************************************/ +/** +* Determines if a DMA_Device_t is "valid". +* +* @return +* TRUE - dma device is valid +* FALSE - dma device isn't valid +*/ +/****************************************************************************/ + +static inline int IsDeviceValid(DMA_Device_t device) +{ + return (device >= 0) && (device < DMA_NUM_DEVICE_ENTRIES); +} + +/****************************************************************************/ +/** +* Translates a DMA handle into a pointer to a channel. +* +* @return +* non-NULL - pointer to DMA_Channel_t +* NULL - DMA Handle was invalid +*/ +/****************************************************************************/ + +static inline DMA_Channel_t *HandleToChannel(DMA_Handle_t handle) +{ + int controllerIdx; + int channelIdx; + + controllerIdx = CONTROLLER_FROM_HANDLE(handle); + channelIdx = CHANNEL_FROM_HANDLE(handle); + + if ((controllerIdx > DMA_NUM_CONTROLLERS) + || (channelIdx > DMA_NUM_CHANNELS)) { + return NULL; + } + return &gDMA.controller[controllerIdx].channel[channelIdx]; +} + +/****************************************************************************/ +/** +* Interrupt handler which is called to process DMA interrupts. +*/ +/****************************************************************************/ + +static irqreturn_t dma_interrupt_handler(int irq, void *dev_id) +{ + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + int irqStatus; + + channel = (DMA_Channel_t *) dev_id; + + /* Figure out why we were called, and knock down the interrupt */ + + irqStatus = dmacHw_getInterruptStatus(channel->dmacHwHandle); + dmacHw_clearInterrupt(channel->dmacHwHandle); + + if ((channel->devType < 0) + || (channel->devType > DMA_NUM_DEVICE_ENTRIES)) { + printk(KERN_ERR "dma_interrupt_handler: Invalid devType: %d\n", + channel->devType); + return IRQ_NONE; + } + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + /* Update stats */ + + if ((irqStatus & dmacHw_INTERRUPT_STATUS_TRANS) != 0) { + devAttr->transferTicks += + (timer_get_tick_count() - devAttr->transferStartTime); + } + + if ((irqStatus & dmacHw_INTERRUPT_STATUS_ERROR) != 0) { + printk(KERN_ERR + "dma_interrupt_handler: devType :%d DMA error (%s)\n", + channel->devType, devAttr->name); + } else { + devAttr->numTransfers++; + devAttr->transferBytes += devAttr->numBytes; + } + + /* Call any installed handler */ + + if (devAttr->devHandler != NULL) { + devAttr->devHandler(channel->devType, irqStatus, + devAttr->userData); + } + + return IRQ_HANDLED; +} + +/****************************************************************************/ +/** +* Allocates memory to hold a descriptor ring. The descriptor ring then +* needs to be populated by making one or more calls to +* dna_add_descriptors. +* +* The returned descriptor ring will be automatically initialized. +* +* @return +* 0 Descriptor ring was allocated successfully +* -EINVAL Invalid parameters passed in +* -ENOMEM Unable to allocate memory for the desired number of descriptors. +*/ +/****************************************************************************/ + +int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to populate */ + int numDescriptors /* Number of descriptors that need to be allocated. */ + ) { + size_t bytesToAlloc = dmacHw_descriptorLen(numDescriptors); + + if ((ring == NULL) || (numDescriptors <= 0)) { + return -EINVAL; + } + + ring->physAddr = 0; + ring->descriptorsAllocated = 0; + ring->bytesAllocated = 0; + + ring->virtAddr = dma_alloc_writecombine(NULL, + bytesToAlloc, + &ring->physAddr, + GFP_KERNEL); + if (ring->virtAddr == NULL) { + return -ENOMEM; + } + + ring->bytesAllocated = bytesToAlloc; + ring->descriptorsAllocated = numDescriptors; + + return dma_init_descriptor_ring(ring, numDescriptors); +} + +EXPORT_SYMBOL(dma_alloc_descriptor_ring); + +/****************************************************************************/ +/** +* Releases the memory which was previously allocated for a descriptor ring. +*/ +/****************************************************************************/ + +void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring /* Descriptor to release */ + ) { + if (ring->virtAddr != NULL) { + dma_free_writecombine(NULL, + ring->bytesAllocated, + ring->virtAddr, ring->physAddr); + } + + ring->bytesAllocated = 0; + ring->descriptorsAllocated = 0; + ring->virtAddr = NULL; + ring->physAddr = 0; +} + +EXPORT_SYMBOL(dma_free_descriptor_ring); + +/****************************************************************************/ +/** +* Initializes a descriptor ring, so that descriptors can be added to it. +* Once a descriptor ring has been allocated, it may be reinitialized for +* use with additional/different regions of memory. +* +* Note that if 7 descriptors are allocated, it's perfectly acceptable to +* initialize the ring with a smaller number of descriptors. The amount +* of memory allocated for the descriptor ring will not be reduced, and +* the descriptor ring may be reinitialized later +* +* @return +* 0 Descriptor ring was initialized successfully +* -ENOMEM The descriptor which was passed in has insufficient space +* to hold the desired number of descriptors. +*/ +/****************************************************************************/ + +int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to initialize */ + int numDescriptors /* Number of descriptors to initialize. */ + ) { + if (ring->virtAddr == NULL) { + return -EINVAL; + } + if (dmacHw_initDescriptor(ring->virtAddr, + ring->physAddr, + ring->bytesAllocated, numDescriptors) < 0) { + printk(KERN_ERR + "dma_init_descriptor_ring: dmacHw_initDescriptor failed\n"); + return -ENOMEM; + } + + return 0; +} + +EXPORT_SYMBOL(dma_init_descriptor_ring); + +/****************************************************************************/ +/** +* Determines the number of descriptors which would be required for a +* transfer of the indicated memory region. +* +* This function also needs to know which DMA device this transfer will +* be destined for, so that the appropriate DMA configuration can be retrieved. +* DMA parameters such as transfer width, and whether this is a memory-to-memory +* or memory-to-peripheral, etc can all affect the actual number of descriptors +* required. +* +* @return +* > 0 Returns the number of descriptors required for the indicated transfer +* -ENODEV - Device handed in is invalid. +* -EINVAL Invalid parameters +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_calculate_descriptor_count(DMA_Device_t device, /* DMA Device that this will be associated with */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ) { + int numDescriptors; + DMA_DeviceAttribute_t *devAttr; + + if (!IsDeviceValid(device)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[device]; + + numDescriptors = dmacHw_calculateDescriptorCount(&devAttr->config, + (void *)srcData, + (void *)dstData, + numBytes); + if (numDescriptors < 0) { + printk(KERN_ERR + "dma_calculate_descriptor_count: dmacHw_calculateDescriptorCount failed\n"); + return -EINVAL; + } + + return numDescriptors; +} + +EXPORT_SYMBOL(dma_calculate_descriptor_count); + +/****************************************************************************/ +/** +* Adds a region of memory to the descriptor ring. Note that it may take +* multiple descriptors for each region of memory. It is the callers +* responsibility to allocate a sufficiently large descriptor ring. +* +* @return +* 0 Descriptors were added successfully +* -ENODEV Device handed in is invalid. +* -EINVAL Invalid parameters +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_add_descriptors(DMA_DescriptorRing_t *ring, /* Descriptor ring to add descriptors to */ + DMA_Device_t device, /* DMA Device that descriptors are for */ + dma_addr_t srcData, /* Place to get data (memory or device) */ + dma_addr_t dstData, /* Place to put data (memory or device) */ + size_t numBytes /* Number of bytes to transfer to the device */ + ) { + int rc; + DMA_DeviceAttribute_t *devAttr; + + if (!IsDeviceValid(device)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[device]; + + rc = dmacHw_setDataDescriptor(&devAttr->config, + ring->virtAddr, + (void *)srcData, + (void *)dstData, numBytes); + if (rc < 0) { + printk(KERN_ERR + "dma_add_descriptors: dmacHw_setDataDescriptor failed with code: %d\n", + rc); + return -ENOMEM; + } + + return 0; +} + +EXPORT_SYMBOL(dma_add_descriptors); + +/****************************************************************************/ +/** +* Sets the descriptor ring associated with a device. +* +* Once set, the descriptor ring will be associated with the device, even +* across channel request/free calls. Passing in a NULL descriptor ring +* will release any descriptor ring currently associated with the device. +* +* Note: If you call dma_transfer, or one of the other dma_alloc_ functions +* the descriptor ring may be released and reallocated. +* +* Note: This function will release the descriptor memory for any current +* descriptor ring associated with this device. +* +* @return +* 0 Descriptors were added successfully +* -ENODEV Device handed in is invalid. +*/ +/****************************************************************************/ + +int dma_set_device_descriptor_ring(DMA_Device_t device, /* Device to update the descriptor ring for. */ + DMA_DescriptorRing_t *ring /* Descriptor ring to add descriptors to */ + ) { + DMA_DeviceAttribute_t *devAttr; + + if (!IsDeviceValid(device)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[device]; + + /* Free the previously allocated descriptor ring */ + + dma_free_descriptor_ring(&devAttr->ring); + + if (ring != NULL) { + /* Copy in the new one */ + + devAttr->ring = *ring; + } + + /* Set things up so that if dma_transfer is called then this descriptor */ + /* ring will get freed. */ + + devAttr->prevSrcData = 0; + devAttr->prevDstData = 0; + devAttr->prevNumBytes = 0; + + return 0; +} + +EXPORT_SYMBOL(dma_set_device_descriptor_ring); + +/****************************************************************************/ +/** +* Retrieves the descriptor ring associated with a device. +* +* @return +* 0 Descriptors were added successfully +* -ENODEV Device handed in is invalid. +*/ +/****************************************************************************/ + +int dma_get_device_descriptor_ring(DMA_Device_t device, /* Device to retrieve the descriptor ring for. */ + DMA_DescriptorRing_t *ring /* Place to store retrieved ring */ + ) { + DMA_DeviceAttribute_t *devAttr; + + memset(ring, 0, sizeof(*ring)); + + if (!IsDeviceValid(device)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[device]; + + *ring = devAttr->ring; + + return 0; +} + +EXPORT_SYMBOL(dma_get_device_descriptor_ring); + +/****************************************************************************/ +/** +* Configures a DMA channel. +* +* @return +* >= 0 - Initialization was successfull. +* +* -EBUSY - Device is currently being used. +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +static int ConfigChannel(DMA_Handle_t handle) +{ + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + int controllerIdx; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[channel->devType]; + controllerIdx = CONTROLLER_FROM_HANDLE(handle); + + if ((devAttr->flags & DMA_DEVICE_FLAG_PORT_PER_DMAC) != 0) { + if (devAttr->config.transferType == + dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL) { + devAttr->config.dstPeripheralPort = + devAttr->dmacPort[controllerIdx]; + } else if (devAttr->config.transferType == + dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM) { + devAttr->config.srcPeripheralPort = + devAttr->dmacPort[controllerIdx]; + } + } + + if (dmacHw_configChannel(channel->dmacHwHandle, &devAttr->config) != 0) { + printk(KERN_ERR "ConfigChannel: dmacHw_configChannel failed\n"); + return -EIO; + } + + return 0; +} + +/****************************************************************************/ +/** +* Intializes all of the data structures associated with the DMA. +* @return +* >= 0 - Initialization was successfull. +* +* -EBUSY - Device is currently being used. +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +int dma_init(void) +{ + int rc = 0; + int controllerIdx; + int channelIdx; + DMA_Device_t devIdx; + DMA_Channel_t *channel; + DMA_Handle_t dedicatedHandle; + + memset(&gDMA, 0, sizeof(gDMA)); + + init_MUTEX_LOCKED(&gDMA.lock); + init_waitqueue_head(&gDMA.freeChannelQ); + + /* Initialize the Hardware */ + + dmacHw_initDma(); + + /* Start off by marking all of the DMA channels as shared. */ + + for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS; + controllerIdx++) { + for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; + channelIdx++) { + channel = + &gDMA.controller[controllerIdx].channel[channelIdx]; + + channel->flags = 0; + channel->devType = DMA_DEVICE_NONE; + channel->lastDevType = DMA_DEVICE_NONE; + +#if (DMA_DEBUG_TRACK_RESERVATION) + channel->fileName = ""; + channel->lineNum = 0; +#endif + + channel->dmacHwHandle = + dmacHw_getChannelHandle(dmacHw_MAKE_CHANNEL_ID + (controllerIdx, + channelIdx)); + dmacHw_initChannel(channel->dmacHwHandle); + } + } + + /* Record any special attributes that channels may have */ + + gDMA.controller[0].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; + gDMA.controller[0].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; + gDMA.controller[1].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; + gDMA.controller[1].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; + + /* Now walk through and record the dedicated channels. */ + + for (devIdx = 0; devIdx < DMA_NUM_DEVICE_ENTRIES; devIdx++) { + DMA_DeviceAttribute_t *devAttr = &DMA_gDeviceAttribute[devIdx]; + + if (((devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) != 0) + && ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) == 0)) { + printk(KERN_ERR + "DMA Device: %s Can only request NO_ISR for dedicated devices\n", + devAttr->name); + rc = -EINVAL; + goto out; + } + + if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { + /* This is a dedicated device. Mark the channel as being reserved. */ + + if (devAttr->dedicatedController >= DMA_NUM_CONTROLLERS) { + printk(KERN_ERR + "DMA Device: %s DMA Controller %d is out of range\n", + devAttr->name, + devAttr->dedicatedController); + rc = -EINVAL; + goto out; + } + + if (devAttr->dedicatedChannel >= DMA_NUM_CHANNELS) { + printk(KERN_ERR + "DMA Device: %s DMA Channel %d is out of range\n", + devAttr->name, + devAttr->dedicatedChannel); + rc = -EINVAL; + goto out; + } + + dedicatedHandle = + MAKE_HANDLE(devAttr->dedicatedController, + devAttr->dedicatedChannel); + channel = HandleToChannel(dedicatedHandle); + + if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) != + 0) { + printk + ("DMA Device: %s attempting to use same DMA Controller:Channel (%d:%d) as %s\n", + devAttr->name, + devAttr->dedicatedController, + devAttr->dedicatedChannel, + DMA_gDeviceAttribute[channel->devType]. + name); + rc = -EBUSY; + goto out; + } + + channel->flags |= DMA_CHANNEL_FLAG_IS_DEDICATED; + channel->devType = devIdx; + + if (devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) { + channel->flags |= DMA_CHANNEL_FLAG_NO_ISR; + } + + /* For dedicated channels, we can go ahead and configure the DMA channel now */ + /* as well. */ + + ConfigChannel(dedicatedHandle); + } + } + + /* Go through and register the interrupt handlers */ + + for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS; + controllerIdx++) { + for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; + channelIdx++) { + channel = + &gDMA.controller[controllerIdx].channel[channelIdx]; + + if ((channel->flags & DMA_CHANNEL_FLAG_NO_ISR) == 0) { + snprintf(channel->name, sizeof(channel->name), + "dma %d:%d %s", controllerIdx, + channelIdx, + channel->devType == + DMA_DEVICE_NONE ? "" : + DMA_gDeviceAttribute[channel->devType]. + name); + + rc = + request_irq(IRQ_DMA0C0 + + (controllerIdx * + DMA_NUM_CHANNELS) + + channelIdx, + dma_interrupt_handler, + IRQF_DISABLED, channel->name, + channel); + if (rc != 0) { + printk(KERN_ERR + "request_irq for IRQ_DMA%dC%d failed\n", + controllerIdx, channelIdx); + } + } + } + } + + /* Create /proc/dma/channels and /proc/dma/devices */ + + gDmaDir = create_proc_entry("dma", S_IFDIR | S_IRUGO | S_IXUGO, NULL); + + if (gDmaDir == NULL) { + printk(KERN_ERR "Unable to create /proc/dma\n"); + } else { + create_proc_read_entry("channels", 0, gDmaDir, + dma_proc_read_channels, NULL); + create_proc_read_entry("devices", 0, gDmaDir, + dma_proc_read_devices, NULL); + create_proc_read_entry("mem-type", 0, gDmaDir, + dma_proc_read_mem_type, NULL); + } + +out: + + up(&gDMA.lock); + + return rc; +} + +/****************************************************************************/ +/** +* Reserves a channel for use with @a dev. If the device is setup to use +* a shared channel, then this function will block until a free channel +* becomes available. +* +* @return +* >= 0 - A valid DMA Handle. +* -EBUSY - Device is currently being used. +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +#if (DMA_DEBUG_TRACK_RESERVATION) +DMA_Handle_t dma_request_channel_dbg + (DMA_Device_t dev, const char *fileName, int lineNum) +#else +DMA_Handle_t dma_request_channel(DMA_Device_t dev) +#endif +{ + DMA_Handle_t handle; + DMA_DeviceAttribute_t *devAttr; + DMA_Channel_t *channel; + int controllerIdx; + int controllerIdx2; + int channelIdx; + + if (down_interruptible(&gDMA.lock) < 0) { + return -ERESTARTSYS; + } + + if ((dev < 0) || (dev >= DMA_NUM_DEVICE_ENTRIES)) { + handle = -ENODEV; + goto out; + } + devAttr = &DMA_gDeviceAttribute[dev]; + +#if (DMA_DEBUG_TRACK_RESERVATION) + { + char *s; + + s = strrchr(fileName, '/'); + if (s != NULL) { + fileName = s + 1; + } + } +#endif + if ((devAttr->flags & DMA_DEVICE_FLAG_IN_USE) != 0) { + /* This device has already been requested and not been freed */ + + printk(KERN_ERR "%s: device %s is already requested\n", + __func__, devAttr->name); + handle = -EBUSY; + goto out; + } + + if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { + /* This device has a dedicated channel. */ + + channel = + &gDMA.controller[devAttr->dedicatedController]. + channel[devAttr->dedicatedChannel]; + if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) { + handle = -EBUSY; + goto out; + } + + channel->flags |= DMA_CHANNEL_FLAG_IN_USE; + devAttr->flags |= DMA_DEVICE_FLAG_IN_USE; + +#if (DMA_DEBUG_TRACK_RESERVATION) + channel->fileName = fileName; + channel->lineNum = lineNum; +#endif + handle = + MAKE_HANDLE(devAttr->dedicatedController, + devAttr->dedicatedChannel); + goto out; + } + + /* This device needs to use one of the shared channels. */ + + handle = DMA_INVALID_HANDLE; + while (handle == DMA_INVALID_HANDLE) { + /* Scan through the shared channels and see if one is available */ + + for (controllerIdx2 = 0; controllerIdx2 < DMA_NUM_CONTROLLERS; + controllerIdx2++) { + /* Check to see if we should try on controller 1 first. */ + + controllerIdx = controllerIdx2; + if ((devAttr-> + flags & DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST) != 0) { + controllerIdx = 1 - controllerIdx; + } + + /* See if the device is available on the controller being tested */ + + if ((devAttr-> + flags & (DMA_DEVICE_FLAG_ON_DMA0 << controllerIdx)) + != 0) { + for (channelIdx = 0; + channelIdx < DMA_NUM_CHANNELS; + channelIdx++) { + channel = + &gDMA.controller[controllerIdx]. + channel[channelIdx]; + + if (((channel-> + flags & + DMA_CHANNEL_FLAG_IS_DEDICATED) == + 0) + && + ((channel-> + flags & DMA_CHANNEL_FLAG_IN_USE) + == 0)) { + if (((channel-> + flags & + DMA_CHANNEL_FLAG_LARGE_FIFO) + != 0) + && + ((devAttr-> + flags & + DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO) + == 0)) { + /* This channel is a large fifo - don't tie it up */ + /* with devices that we don't want using it. */ + + continue; + } + + channel->flags |= + DMA_CHANNEL_FLAG_IN_USE; + channel->devType = dev; + devAttr->flags |= + DMA_DEVICE_FLAG_IN_USE; + +#if (DMA_DEBUG_TRACK_RESERVATION) + channel->fileName = fileName; + channel->lineNum = lineNum; +#endif + handle = + MAKE_HANDLE(controllerIdx, + channelIdx); + + /* Now that we've reserved the channel - we can go ahead and configure it */ + + if (ConfigChannel(handle) != 0) { + handle = -EIO; + printk(KERN_ERR + "dma_request_channel: ConfigChannel failed\n"); + } + goto out; + } + } + } + } + + /* No channels are currently available. Let's wait for one to free up. */ + + { + DEFINE_WAIT(wait); + + prepare_to_wait(&gDMA.freeChannelQ, &wait, + TASK_INTERRUPTIBLE); + up(&gDMA.lock); + schedule(); + finish_wait(&gDMA.freeChannelQ, &wait); + + if (signal_pending(current)) { + /* We don't currently hold gDMA.lock, so we return directly */ + + return -ERESTARTSYS; + } + } + + if (down_interruptible(&gDMA.lock)) { + return -ERESTARTSYS; + } + } + +out: + up(&gDMA.lock); + + return handle; +} + +/* Create both _dbg and non _dbg functions for modules. */ + +#if (DMA_DEBUG_TRACK_RESERVATION) +#undef dma_request_channel +DMA_Handle_t dma_request_channel(DMA_Device_t dev) +{ + return dma_request_channel_dbg(dev, __FILE__, __LINE__); +} + +EXPORT_SYMBOL(dma_request_channel_dbg); +#endif +EXPORT_SYMBOL(dma_request_channel); + +/****************************************************************************/ +/** +* Frees a previously allocated DMA Handle. +*/ +/****************************************************************************/ + +int dma_free_channel(DMA_Handle_t handle /* DMA handle. */ + ) { + int rc = 0; + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + + if (down_interruptible(&gDMA.lock) < 0) { + return -ERESTARTSYS; + } + + channel = HandleToChannel(handle); + if (channel == NULL) { + rc = -EINVAL; + goto out; + } + + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) == 0) { + channel->lastDevType = channel->devType; + channel->devType = DMA_DEVICE_NONE; + } + channel->flags &= ~DMA_CHANNEL_FLAG_IN_USE; + devAttr->flags &= ~DMA_DEVICE_FLAG_IN_USE; + +out: + up(&gDMA.lock); + + wake_up_interruptible(&gDMA.freeChannelQ); + + return rc; +} + +EXPORT_SYMBOL(dma_free_channel); + +/****************************************************************************/ +/** +* Determines if a given device has been configured as using a shared +* channel. +* +* @return +* 0 Device uses a dedicated channel +* > zero Device uses a shared channel +* < zero Error code +*/ +/****************************************************************************/ + +int dma_device_is_channel_shared(DMA_Device_t device /* Device to check. */ + ) { + DMA_DeviceAttribute_t *devAttr; + + if (!IsDeviceValid(device)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[device]; + + return ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) == 0); +} + +EXPORT_SYMBOL(dma_device_is_channel_shared); + +/****************************************************************************/ +/** +* Allocates buffers for the descriptors. This is normally done automatically +* but needs to be done explicitly when initiating a dma from interrupt +* context. +* +* @return +* 0 Descriptors were allocated successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_alloc_descriptors(DMA_Handle_t handle, /* DMA Handle */ + dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ) { + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + int numDescriptors; + size_t ringBytesRequired; + int rc = 0; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + if (devAttr->config.transferType != transferType) { + return -EINVAL; + } + + /* Figure out how many descriptors we need. */ + + /* printk("srcData: 0x%08x dstData: 0x%08x, numBytes: %d\n", */ + /* srcData, dstData, numBytes); */ + + numDescriptors = dmacHw_calculateDescriptorCount(&devAttr->config, + (void *)srcData, + (void *)dstData, + numBytes); + if (numDescriptors < 0) { + printk(KERN_ERR "%s: dmacHw_calculateDescriptorCount failed\n", + __func__); + return -EINVAL; + } + + /* Check to see if we can reuse the existing descriptor ring, or if we need to allocate */ + /* a new one. */ + + ringBytesRequired = dmacHw_descriptorLen(numDescriptors); + + /* printk("ringBytesRequired: %d\n", ringBytesRequired); */ + + if (ringBytesRequired > devAttr->ring.bytesAllocated) { + /* Make sure that this code path is never taken from interrupt context. */ + /* It's OK for an interrupt to initiate a DMA transfer, but the descriptor */ + /* allocation needs to have already been done. */ + + might_sleep(); + + /* Free the old descriptor ring and allocate a new one. */ + + dma_free_descriptor_ring(&devAttr->ring); + + /* And allocate a new one. */ + + rc = + dma_alloc_descriptor_ring(&devAttr->ring, + numDescriptors); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_alloc_descriptor_ring(%d) failed\n", + __func__, numDescriptors); + return rc; + } + /* Setup the descriptor for this transfer */ + + if (dmacHw_initDescriptor(devAttr->ring.virtAddr, + devAttr->ring.physAddr, + devAttr->ring.bytesAllocated, + numDescriptors) < 0) { + printk(KERN_ERR "%s: dmacHw_initDescriptor failed\n", + __func__); + return -EINVAL; + } + } else { + /* We've already got enough ring buffer allocated. All we need to do is reset */ + /* any control information, just in case the previous DMA was stopped. */ + + dmacHw_resetDescriptorControl(devAttr->ring.virtAddr); + } + + /* dma_alloc/free both set the prevSrc/DstData to 0. If they happen to be the same */ + /* as last time, then we don't need to call setDataDescriptor again. */ + + if (dmacHw_setDataDescriptor(&devAttr->config, + devAttr->ring.virtAddr, + (void *)srcData, + (void *)dstData, numBytes) < 0) { + printk(KERN_ERR "%s: dmacHw_setDataDescriptor failed\n", + __func__); + return -EINVAL; + } + + /* Remember the critical information for this transfer so that we can eliminate */ + /* another call to dma_alloc_descriptors if the caller reuses the same buffers */ + + devAttr->prevSrcData = srcData; + devAttr->prevDstData = dstData; + devAttr->prevNumBytes = numBytes; + + return 0; +} + +EXPORT_SYMBOL(dma_alloc_descriptors); + +/****************************************************************************/ +/** +* Allocates and sets up descriptors for a double buffered circular buffer. +* +* This is primarily intended to be used for things like the ingress samples +* from a microphone. +* +* @return +* > 0 Number of descriptors actually allocated. +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) +* -ENOMEM Memory exhausted +*/ +/****************************************************************************/ + +int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */ + dma_addr_t srcData, /* Physical address of source data */ + dma_addr_t dstData1, /* Physical address of first destination buffer */ + dma_addr_t dstData2, /* Physical address of second destination buffer */ + size_t numBytes /* Number of bytes in each destination buffer */ + ) { + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + int numDst1Descriptors; + int numDst2Descriptors; + int numDescriptors; + size_t ringBytesRequired; + int rc = 0; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + /* Figure out how many descriptors we need. */ + + /* printk("srcData: 0x%08x dstData: 0x%08x, numBytes: %d\n", */ + /* srcData, dstData, numBytes); */ + + numDst1Descriptors = + dmacHw_calculateDescriptorCount(&devAttr->config, (void *)srcData, + (void *)dstData1, numBytes); + if (numDst1Descriptors < 0) { + return -EINVAL; + } + numDst2Descriptors = + dmacHw_calculateDescriptorCount(&devAttr->config, (void *)srcData, + (void *)dstData2, numBytes); + if (numDst2Descriptors < 0) { + return -EINVAL; + } + numDescriptors = numDst1Descriptors + numDst2Descriptors; + /* printk("numDescriptors: %d\n", numDescriptors); */ + + /* Check to see if we can reuse the existing descriptor ring, or if we need to allocate */ + /* a new one. */ + + ringBytesRequired = dmacHw_descriptorLen(numDescriptors); + + /* printk("ringBytesRequired: %d\n", ringBytesRequired); */ + + if (ringBytesRequired > devAttr->ring.bytesAllocated) { + /* Make sure that this code path is never taken from interrupt context. */ + /* It's OK for an interrupt to initiate a DMA transfer, but the descriptor */ + /* allocation needs to have already been done. */ + + might_sleep(); + + /* Free the old descriptor ring and allocate a new one. */ + + dma_free_descriptor_ring(&devAttr->ring); + + /* And allocate a new one. */ + + rc = + dma_alloc_descriptor_ring(&devAttr->ring, + numDescriptors); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_alloc_descriptor_ring(%d) failed\n", + __func__, ringBytesRequired); + return rc; + } + } + + /* Setup the descriptor for this transfer. Since this function is used with */ + /* CONTINUOUS DMA operations, we need to reinitialize every time, otherwise */ + /* setDataDescriptor will keep trying to append onto the end. */ + + if (dmacHw_initDescriptor(devAttr->ring.virtAddr, + devAttr->ring.physAddr, + devAttr->ring.bytesAllocated, + numDescriptors) < 0) { + printk(KERN_ERR "%s: dmacHw_initDescriptor failed\n", __func__); + return -EINVAL; + } + + /* dma_alloc/free both set the prevSrc/DstData to 0. If they happen to be the same */ + /* as last time, then we don't need to call setDataDescriptor again. */ + + if (dmacHw_setDataDescriptor(&devAttr->config, + devAttr->ring.virtAddr, + (void *)srcData, + (void *)dstData1, numBytes) < 0) { + printk(KERN_ERR "%s: dmacHw_setDataDescriptor 1 failed\n", + __func__); + return -EINVAL; + } + if (dmacHw_setDataDescriptor(&devAttr->config, + devAttr->ring.virtAddr, + (void *)srcData, + (void *)dstData2, numBytes) < 0) { + printk(KERN_ERR "%s: dmacHw_setDataDescriptor 2 failed\n", + __func__); + return -EINVAL; + } + + /* You should use dma_start_transfer rather than dma_transfer_xxx so we don't */ + /* try to make the 'prev' variables right. */ + + devAttr->prevSrcData = 0; + devAttr->prevDstData = 0; + devAttr->prevNumBytes = 0; + + return numDescriptors; +} + +EXPORT_SYMBOL(dma_alloc_double_dst_descriptors); + +/****************************************************************************/ +/** +* Initiates a transfer when the descriptors have already been setup. +* +* This is a special case, and normally, the dma_transfer_xxx functions should +* be used. +* +* @return +* 0 Transfer was started successfully +* -ENODEV Invalid handle +*/ +/****************************************************************************/ + +int dma_start_transfer(DMA_Handle_t handle) +{ + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + dmacHw_initiateTransfer(channel->dmacHwHandle, &devAttr->config, + devAttr->ring.virtAddr); + + /* Since we got this far, everything went successfully */ + + return 0; +} + +EXPORT_SYMBOL(dma_start_transfer); + +/****************************************************************************/ +/** +* Stops a previously started DMA transfer. +* +* @return +* 0 Transfer was stopped successfully +* -ENODEV Invalid handle +*/ +/****************************************************************************/ + +int dma_stop_transfer(DMA_Handle_t handle) +{ + DMA_Channel_t *channel; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + + dmacHw_stopTransfer(channel->dmacHwHandle); + + return 0; +} + +EXPORT_SYMBOL(dma_stop_transfer); + +/****************************************************************************/ +/** +* Waits for a DMA to complete by polling. This function is only intended +* to be used for testing. Interrupts should be used for most DMA operations. +*/ +/****************************************************************************/ + +int dma_wait_transfer_done(DMA_Handle_t handle) +{ + DMA_Channel_t *channel; + dmacHw_TRANSFER_STATUS_e status; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + + while ((status = + dmacHw_transferCompleted(channel->dmacHwHandle)) == + dmacHw_TRANSFER_STATUS_BUSY) { + ; + } + + if (status == dmacHw_TRANSFER_STATUS_ERROR) { + printk(KERN_ERR "%s: DMA transfer failed\n", __func__); + return -EIO; + } + return 0; +} + +EXPORT_SYMBOL(dma_wait_transfer_done); + +/****************************************************************************/ +/** +* Initiates a DMA, allocating the descriptors as required. +* +* @return +* 0 Transfer was started successfully +* -EINVAL Invalid device type for this kind of transfer +* (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV) +*/ +/****************************************************************************/ + +int dma_transfer(DMA_Handle_t handle, /* DMA Handle */ + dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ + dma_addr_t srcData, /* Place to get data to write to device */ + dma_addr_t dstData, /* Pointer to device data address */ + size_t numBytes /* Number of bytes to transfer to the device */ + ) { + DMA_Channel_t *channel; + DMA_DeviceAttribute_t *devAttr; + int rc = 0; + + channel = HandleToChannel(handle); + if (channel == NULL) { + return -ENODEV; + } + + devAttr = &DMA_gDeviceAttribute[channel->devType]; + + if (devAttr->config.transferType != transferType) { + return -EINVAL; + } + + /* We keep track of the information about the previous request for this */ + /* device, and if the attributes match, then we can use the descriptors we setup */ + /* the last time, and not have to reinitialize everything. */ + + { + rc = + dma_alloc_descriptors(handle, transferType, srcData, + dstData, numBytes); + if (rc != 0) { + return rc; + } + } + + /* And kick off the transfer */ + + devAttr->numBytes = numBytes; + devAttr->transferStartTime = timer_get_tick_count(); + + dmacHw_initiateTransfer(channel->dmacHwHandle, &devAttr->config, + devAttr->ring.virtAddr); + + /* Since we got this far, everything went successfully */ + + return 0; +} + +EXPORT_SYMBOL(dma_transfer); + +/****************************************************************************/ +/** +* Set the callback function which will be called when a transfer completes. +* If a NULL callback function is set, then no callback will occur. +* +* @note @a devHandler will be called from IRQ context. +* +* @return +* 0 - Success +* -ENODEV - Device handed in is invalid. +*/ +/****************************************************************************/ + +int dma_set_device_handler(DMA_Device_t dev, /* Device to set the callback for. */ + DMA_DeviceHandler_t devHandler, /* Function to call when the DMA completes */ + void *userData /* Pointer which will be passed to devHandler. */ + ) { + DMA_DeviceAttribute_t *devAttr; + unsigned long flags; + + if (!IsDeviceValid(dev)) { + return -ENODEV; + } + devAttr = &DMA_gDeviceAttribute[dev]; + + local_irq_save(flags); + + devAttr->userData = userData; + devAttr->devHandler = devHandler; + + local_irq_restore(flags); + + return 0; +} + +EXPORT_SYMBOL(dma_set_device_handler); + +/****************************************************************************/ +/** +* Initializes a memory mapping structure +*/ +/****************************************************************************/ + +int dma_init_mem_map(DMA_MemMap_t *memMap) +{ + memset(memMap, 0, sizeof(*memMap)); + + init_MUTEX(&memMap->lock); + + return 0; +} + +EXPORT_SYMBOL(dma_init_mem_map); + +/****************************************************************************/ +/** +* Releases any memory currently being held by a memory mapping structure. +*/ +/****************************************************************************/ + +int dma_term_mem_map(DMA_MemMap_t *memMap) +{ + down(&memMap->lock); /* Just being paranoid */ + + /* Free up any allocated memory */ + + up(&memMap->lock); + memset(memMap, 0, sizeof(*memMap)); + + return 0; +} + +EXPORT_SYMBOL(dma_term_mem_map); + +/****************************************************************************/ +/** +* Looks at a memory address and categorizes it. +* +* @return One of the values from the DMA_MemType_t enumeration. +*/ +/****************************************************************************/ + +DMA_MemType_t dma_mem_type(void *addr) +{ + unsigned long addrVal = (unsigned long)addr; + + if (addrVal >= VMALLOC_END) { + /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */ + + /* dma_alloc_xxx pages are physically and virtually contiguous */ + + return DMA_MEM_TYPE_DMA; + } + + /* Technically, we could add one more classification. Addresses between VMALLOC_END */ + /* and the beginning of the DMA virtual address could be considered to be I/O space. */ + /* Right now, nobody cares about this particular classification, so we ignore it. */ + + if (is_vmalloc_addr(addr)) { + /* Address comes from the vmalloc'd region. Pages are virtually */ + /* contiguous but NOT physically contiguous */ + + return DMA_MEM_TYPE_VMALLOC; + } + + if (addrVal >= PAGE_OFFSET) { + /* PAGE_OFFSET is typically 0xC0000000 */ + + /* kmalloc'd pages are physically contiguous */ + + return DMA_MEM_TYPE_KMALLOC; + } + + return DMA_MEM_TYPE_USER; +} + +EXPORT_SYMBOL(dma_mem_type); + +/****************************************************************************/ +/** +* Looks at a memory address and determines if we support DMA'ing to/from +* that type of memory. +* +* @return boolean - +* return value != 0 means dma supported +* return value == 0 means dma not supported +*/ +/****************************************************************************/ + +int dma_mem_supports_dma(void *addr) +{ + DMA_MemType_t memType = dma_mem_type(addr); + + return (memType == DMA_MEM_TYPE_DMA) +#if ALLOW_MAP_OF_KMALLOC_MEMORY + || (memType == DMA_MEM_TYPE_KMALLOC) +#endif + || (memType == DMA_MEM_TYPE_USER); +} + +EXPORT_SYMBOL(dma_mem_supports_dma); + +/****************************************************************************/ +/** +* Maps in a memory region such that it can be used for performing a DMA. +* +* @return +*/ +/****************************************************************************/ + +int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */ + enum dma_data_direction dir /* Direction that the mapping will be going */ + ) { + int rc; + + down(&memMap->lock); + + DMA_MAP_PRINT("memMap: %p\n", memMap); + + if (memMap->inUse) { + printk(KERN_ERR "%s: memory map %p is already being used\n", + __func__, memMap); + rc = -EBUSY; + goto out; + } + + memMap->inUse = 1; + memMap->dir = dir; + memMap->numRegionsUsed = 0; + + rc = 0; + +out: + + DMA_MAP_PRINT("returning %d", rc); + + up(&memMap->lock); + + return rc; +} + +EXPORT_SYMBOL(dma_map_start); + +/****************************************************************************/ +/** +* Adds a segment of memory to a memory map. Each segment is both +* physically and virtually contiguous. +* +* @return 0 on success, error code otherwise. +*/ +/****************************************************************************/ + +static int dma_map_add_segment(DMA_MemMap_t *memMap, /* Stores state information about the map */ + DMA_Region_t *region, /* Region that the segment belongs to */ + void *virtAddr, /* Virtual address of the segment being added */ + dma_addr_t physAddr, /* Physical address of the segment being added */ + size_t numBytes /* Number of bytes of the segment being added */ + ) { + DMA_Segment_t *segment; + + DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr, + physAddr, numBytes); + + /* Sanity check */ + + if (((unsigned long)virtAddr < (unsigned long)region->virtAddr) + || (((unsigned long)virtAddr + numBytes)) > + ((unsigned long)region->virtAddr + region->numBytes)) { + printk(KERN_ERR + "%s: virtAddr %p is outside region @ %p len: %d\n", + __func__, virtAddr, region->virtAddr, region->numBytes); + return -EINVAL; + } + + if (region->numSegmentsUsed > 0) { + /* Check to see if this segment is physically contiguous with the previous one */ + + segment = ®ion->segment[region->numSegmentsUsed - 1]; + + if ((segment->physAddr + segment->numBytes) == physAddr) { + /* It is - just add on to the end */ + + DMA_MAP_PRINT("appending %d bytes to last segment\n", + numBytes); + + segment->numBytes += numBytes; + + return 0; + } + } + + /* Reallocate to hold more segments, if required. */ + + if (region->numSegmentsUsed >= region->numSegmentsAllocated) { + DMA_Segment_t *newSegment; + size_t oldSize = + region->numSegmentsAllocated * sizeof(*newSegment); + int newAlloc = region->numSegmentsAllocated + 4; + size_t newSize = newAlloc * sizeof(*newSegment); + + newSegment = kmalloc(newSize, GFP_KERNEL); + if (newSegment == NULL) { + return -ENOMEM; + } + memcpy(newSegment, region->segment, oldSize); + memset(&((uint8_t *) newSegment)[oldSize], 0, + newSize - oldSize); + kfree(region->segment); + + region->numSegmentsAllocated = newAlloc; + region->segment = newSegment; + } + + segment = ®ion->segment[region->numSegmentsUsed]; + region->numSegmentsUsed++; + + segment->virtAddr = virtAddr; + segment->physAddr = physAddr; + segment->numBytes = numBytes; + + DMA_MAP_PRINT("returning success\n"); + + return 0; +} + +/****************************************************************************/ +/** +* Adds a region of memory to a memory map. Each region is virtually +* contiguous, but not necessarily physically contiguous. +* +* @return 0 on success, error code otherwise. +*/ +/****************************************************************************/ + +int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */ + void *mem, /* Virtual address that we want to get a map of */ + size_t numBytes /* Number of bytes being mapped */ + ) { + unsigned long addr = (unsigned long)mem; + unsigned int offset; + int rc = 0; + DMA_Region_t *region; + dma_addr_t physAddr; + + down(&memMap->lock); + + DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes); + + if (!memMap->inUse) { + printk(KERN_ERR "%s: Make sure you call dma_map_start first\n", + __func__); + rc = -EINVAL; + goto out; + } + + /* Reallocate to hold more regions. */ + + if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) { + DMA_Region_t *newRegion; + size_t oldSize = + memMap->numRegionsAllocated * sizeof(*newRegion); + int newAlloc = memMap->numRegionsAllocated + 4; + size_t newSize = newAlloc * sizeof(*newRegion); + + newRegion = kmalloc(newSize, GFP_KERNEL); + if (newRegion == NULL) { + rc = -ENOMEM; + goto out; + } + memcpy(newRegion, memMap->region, oldSize); + memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize); + + kfree(memMap->region); + + memMap->numRegionsAllocated = newAlloc; + memMap->region = newRegion; + } + + region = &memMap->region[memMap->numRegionsUsed]; + memMap->numRegionsUsed++; + + offset = addr & ~PAGE_MASK; + + region->memType = dma_mem_type(mem); + region->virtAddr = mem; + region->numBytes = numBytes; + region->numSegmentsUsed = 0; + region->numLockedPages = 0; + region->lockedPages = NULL; + + switch (region->memType) { + case DMA_MEM_TYPE_VMALLOC: + { + atomic_inc(&gDmaStatMemTypeVmalloc); + + /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */ + + /* vmalloc'd pages are not physically contiguous */ + + rc = -EINVAL; + break; + } + + case DMA_MEM_TYPE_KMALLOC: + { + atomic_inc(&gDmaStatMemTypeKmalloc); + + /* kmalloc'd pages are physically contiguous, so they'll have exactly */ + /* one segment */ + +#if ALLOW_MAP_OF_KMALLOC_MEMORY + physAddr = + dma_map_single(NULL, mem, numBytes, memMap->dir); + rc = dma_map_add_segment(memMap, region, mem, physAddr, + numBytes); +#else + rc = -EINVAL; +#endif + break; + } + + case DMA_MEM_TYPE_DMA: + { + /* dma_alloc_xxx pages are physically contiguous */ + + atomic_inc(&gDmaStatMemTypeCoherent); + + physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset; + + dma_sync_single_for_cpu(NULL, physAddr, numBytes, + memMap->dir); + rc = dma_map_add_segment(memMap, region, mem, physAddr, + numBytes); + break; + } + + case DMA_MEM_TYPE_USER: + { + size_t firstPageOffset; + size_t firstPageSize; + struct page **pages; + struct task_struct *userTask; + + atomic_inc(&gDmaStatMemTypeUser); + +#if 1 + /* If the pages are user pages, then the dma_mem_map_set_user_task function */ + /* must have been previously called. */ + + if (memMap->userTask == NULL) { + printk(KERN_ERR + "%s: must call dma_mem_map_set_user_task when using user-mode memory\n", + __func__); + return -EINVAL; + } + + /* User pages need to be locked. */ + + firstPageOffset = + (unsigned long)region->virtAddr & (PAGE_SIZE - 1); + firstPageSize = PAGE_SIZE - firstPageOffset; + + region->numLockedPages = (firstPageOffset + + region->numBytes + + PAGE_SIZE - 1) / PAGE_SIZE; + pages = + kmalloc(region->numLockedPages * + sizeof(struct page *), GFP_KERNEL); + + if (pages == NULL) { + region->numLockedPages = 0; + return -ENOMEM; + } + + userTask = memMap->userTask; + + down_read(&userTask->mm->mmap_sem); + rc = get_user_pages(userTask, /* task */ + userTask->mm, /* mm */ + (unsigned long)region->virtAddr, /* start */ + region->numLockedPages, /* len */ + memMap->dir == DMA_FROM_DEVICE, /* write */ + 0, /* force */ + pages, /* pages (array of pointers to page) */ + NULL); /* vmas */ + up_read(&userTask->mm->mmap_sem); + + if (rc != region->numLockedPages) { + kfree(pages); + region->numLockedPages = 0; + + if (rc >= 0) { + rc = -EINVAL; + } + } else { + uint8_t *virtAddr = region->virtAddr; + size_t bytesRemaining; + int pageIdx; + + rc = 0; /* Since get_user_pages returns +ve number */ + + region->lockedPages = pages; + + /* We've locked the user pages. Now we need to walk them and figure */ + /* out the physical addresses. */ + + /* The first page may be partial */ + + dma_map_add_segment(memMap, + region, + virtAddr, + PFN_PHYS(page_to_pfn + (pages[0])) + + firstPageOffset, + firstPageSize); + + virtAddr += firstPageSize; + bytesRemaining = + region->numBytes - firstPageSize; + + for (pageIdx = 1; + pageIdx < region->numLockedPages; + pageIdx++) { + size_t bytesThisPage = + (bytesRemaining > + PAGE_SIZE ? PAGE_SIZE : + bytesRemaining); + + DMA_MAP_PRINT + ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n", + pageIdx, pages[pageIdx], + page_to_pfn(pages[pageIdx]), + PFN_PHYS(page_to_pfn + (pages[pageIdx]))); + + dma_map_add_segment(memMap, + region, + virtAddr, + PFN_PHYS(page_to_pfn + (pages + [pageIdx])), + bytesThisPage); + + virtAddr += bytesThisPage; + bytesRemaining -= bytesThisPage; + } + } +#else + printk(KERN_ERR + "%s: User mode pages are not yet supported\n", + __func__); + + /* user pages are not physically contiguous */ + + rc = -EINVAL; +#endif + break; + } + + default: + { + printk(KERN_ERR "%s: Unsupported memory type: %d\n", + __func__, region->memType); + + rc = -EINVAL; + break; + } + } + + if (rc != 0) { + memMap->numRegionsUsed--; + } + +out: + + DMA_MAP_PRINT("returning %d\n", rc); + + up(&memMap->lock); + + return rc; +} + +EXPORT_SYMBOL(dma_map_add_segment); + +/****************************************************************************/ +/** +* Maps in a memory region such that it can be used for performing a DMA. +* +* @return 0 on success, error code otherwise. +*/ +/****************************************************************************/ + +int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */ + void *mem, /* Virtual address that we want to get a map of */ + size_t numBytes, /* Number of bytes being mapped */ + enum dma_data_direction dir /* Direction that the mapping will be going */ + ) { + int rc; + + rc = dma_map_start(memMap, dir); + if (rc == 0) { + rc = dma_map_add_region(memMap, mem, numBytes); + if (rc < 0) { + /* Since the add fails, this function will fail, and the caller won't */ + /* call unmap, so we need to do it here. */ + + dma_unmap(memMap, 0); + } + } + + return rc; +} + +EXPORT_SYMBOL(dma_map_mem); + +/****************************************************************************/ +/** +* Setup a descriptor ring for a given memory map. +* +* It is assumed that the descriptor ring has already been initialized, and +* this routine will only reallocate a new descriptor ring if the existing +* one is too small. +* +* @return 0 on success, error code otherwise. +*/ +/****************************************************************************/ + +int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */ + DMA_MemMap_t *memMap, /* Memory map that will be used */ + dma_addr_t devPhysAddr /* Physical address of device */ + ) { + int rc; + int numDescriptors; + DMA_DeviceAttribute_t *devAttr; + DMA_Region_t *region; + DMA_Segment_t *segment; + dma_addr_t srcPhysAddr; + dma_addr_t dstPhysAddr; + int regionIdx; + int segmentIdx; + + devAttr = &DMA_gDeviceAttribute[dev]; + + down(&memMap->lock); + + /* Figure out how many descriptors we need */ + + numDescriptors = 0; + for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { + region = &memMap->region[regionIdx]; + + for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; + segmentIdx++) { + segment = ®ion->segment[segmentIdx]; + + if (memMap->dir == DMA_TO_DEVICE) { + srcPhysAddr = segment->physAddr; + dstPhysAddr = devPhysAddr; + } else { + srcPhysAddr = devPhysAddr; + dstPhysAddr = segment->physAddr; + } + + rc = + dma_calculate_descriptor_count(dev, srcPhysAddr, + dstPhysAddr, + segment-> + numBytes); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_calculate_descriptor_count failed: %d\n", + __func__, rc); + goto out; + } + numDescriptors += rc; + } + } + + /* Adjust the size of the ring, if it isn't big enough */ + + if (numDescriptors > devAttr->ring.descriptorsAllocated) { + dma_free_descriptor_ring(&devAttr->ring); + rc = + dma_alloc_descriptor_ring(&devAttr->ring, + numDescriptors); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_alloc_descriptor_ring failed: %d\n", + __func__, rc); + goto out; + } + } else { + rc = + dma_init_descriptor_ring(&devAttr->ring, + numDescriptors); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_init_descriptor_ring failed: %d\n", + __func__, rc); + goto out; + } + } + + /* Populate the descriptors */ + + for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { + region = &memMap->region[regionIdx]; + + for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; + segmentIdx++) { + segment = ®ion->segment[segmentIdx]; + + if (memMap->dir == DMA_TO_DEVICE) { + srcPhysAddr = segment->physAddr; + dstPhysAddr = devPhysAddr; + } else { + srcPhysAddr = devPhysAddr; + dstPhysAddr = segment->physAddr; + } + + rc = + dma_add_descriptors(&devAttr->ring, dev, + srcPhysAddr, dstPhysAddr, + segment->numBytes); + if (rc < 0) { + printk(KERN_ERR + "%s: dma_add_descriptors failed: %d\n", + __func__, rc); + goto out; + } + } + } + + rc = 0; + +out: + + up(&memMap->lock); + return rc; +} + +EXPORT_SYMBOL(dma_map_create_descriptor_ring); + +/****************************************************************************/ +/** +* Maps in a memory region such that it can be used for performing a DMA. +* +* @return +*/ +/****************************************************************************/ + +int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ + int dirtied /* non-zero if any of the pages were modified */ + ) { + int regionIdx; + int segmentIdx; + DMA_Region_t *region; + DMA_Segment_t *segment; + + for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { + region = &memMap->region[regionIdx]; + + for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; + segmentIdx++) { + segment = ®ion->segment[segmentIdx]; + + switch (region->memType) { + case DMA_MEM_TYPE_VMALLOC: + { + printk(KERN_ERR + "%s: vmalloc'd pages are not yet supported\n", + __func__); + return -EINVAL; + } + + case DMA_MEM_TYPE_KMALLOC: + { +#if ALLOW_MAP_OF_KMALLOC_MEMORY + dma_unmap_single(NULL, + segment->physAddr, + segment->numBytes, + memMap->dir); +#endif + break; + } + + case DMA_MEM_TYPE_DMA: + { + dma_sync_single_for_cpu(NULL, + segment-> + physAddr, + segment-> + numBytes, + memMap->dir); + break; + } + + case DMA_MEM_TYPE_USER: + { + /* Nothing to do here. */ + + break; + } + + default: + { + printk(KERN_ERR + "%s: Unsupported memory type: %d\n", + __func__, region->memType); + return -EINVAL; + } + } + + segment->virtAddr = NULL; + segment->physAddr = 0; + segment->numBytes = 0; + } + + if (region->numLockedPages > 0) { + int pageIdx; + + /* Some user pages were locked. We need to go and unlock them now. */ + + for (pageIdx = 0; pageIdx < region->numLockedPages; + pageIdx++) { + struct page *page = + region->lockedPages[pageIdx]; + + if (memMap->dir == DMA_FROM_DEVICE) { + SetPageDirty(page); + } + page_cache_release(page); + } + kfree(region->lockedPages); + region->numLockedPages = 0; + region->lockedPages = NULL; + } + + region->memType = DMA_MEM_TYPE_NONE; + region->virtAddr = NULL; + region->numBytes = 0; + region->numSegmentsUsed = 0; + } + memMap->userTask = NULL; + memMap->numRegionsUsed = 0; + memMap->inUse = 0; + + up(&memMap->lock); + + return 0; +} + +EXPORT_SYMBOL(dma_unmap); -- GitLab From 34559125742645843bc7639900c7b4737ec12b72 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:01:47 +0100 Subject: [PATCH 0979/1002] ARM: 5649/1: bcmring: add bcmring timer function bcmring timer helper function, hardware register headers Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/mach/timer.h | 77 ++++++++++++++++++++++ arch/arm/mach-bcmring/include/mach/timex.h | 25 +++++++ arch/arm/mach-bcmring/timer.c | 62 +++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/timer.h create mode 100644 arch/arm/mach-bcmring/include/mach/timex.h create mode 100644 arch/arm/mach-bcmring/timer.c diff --git a/arch/arm/mach-bcmring/include/mach/timer.h b/arch/arm/mach-bcmring/include/mach/timer.h new file mode 100644 index 0000000000000..5a94bbb032b69 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/timer.h @@ -0,0 +1,77 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/* +* +***************************************************************************** +* +* timer.h +* +* PURPOSE: +* +* +* +* NOTES: +* +*****************************************************************************/ + +#if !defined(BCM_LINUX_TIMER_H) +#define BCM_LINUX_TIMER_H + +#if defined(__KERNEL__) + +/* ---- Include Files ---------------------------------------------------- */ +/* ---- Constants and Types ---------------------------------------------- */ + +typedef unsigned int timer_tick_count_t; +typedef unsigned int timer_tick_rate_t; +typedef unsigned int timer_msec_t; + +/* ---- Variable Externs ------------------------------------------------- */ +/* ---- Function Prototypes ---------------------------------------------- */ + +/**************************************************************************** +* +* timer_get_tick_count +* +* +***************************************************************************/ +timer_tick_count_t timer_get_tick_count(void); + +/**************************************************************************** +* +* timer_get_tick_rate +* +* +***************************************************************************/ +timer_tick_rate_t timer_get_tick_rate(void); + +/**************************************************************************** +* +* timer_get_msec +* +* +***************************************************************************/ +timer_msec_t timer_get_msec(void); + +/**************************************************************************** +* +* timer_ticks_to_msec +* +* +***************************************************************************/ +timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks); + +#endif /* __KERNEL__ */ +#endif /* BCM_LINUX_TIMER_H */ diff --git a/arch/arm/mach-bcmring/include/mach/timex.h b/arch/arm/mach-bcmring/include/mach/timex.h new file mode 100644 index 0000000000000..40d033ec58923 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/timex.h @@ -0,0 +1,25 @@ +/* + * + * Integrator architecture timex specifications + * + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Specifies the number of ticks per second + */ +#define CLOCK_TICK_RATE 100000 /* REG_SMT_TICKS_PER_SEC */ diff --git a/arch/arm/mach-bcmring/timer.c b/arch/arm/mach-bcmring/timer.c new file mode 100644 index 0000000000000..2d415d2a8e682 --- /dev/null +++ b/arch/arm/mach-bcmring/timer.c @@ -0,0 +1,62 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include <linux/version.h> +#include <linux/types.h> +#include <linux/module.h> +#include <csp/tmrHw.h> + +#include <mach/timer.h> +/* The core.c file initializes timers 1 and 3 as a linux clocksource. */ +/* The real time clock should probably be the real linux clocksource. */ +/* In the meantime, this file should agree with core.c as to the */ +/* profiling timer. If the clocksource is moved to rtc later, then */ +/* we can init the profiling timer here instead. */ + +/* Timer 1 provides 25MHz resolution syncrhonized to scheduling and APM timing */ +/* Timer 3 provides bus freqeuncy sychronized to ACLK, but spread spectrum will */ +/* affect synchronization with scheduling and APM timing. */ + +#define PROF_TIMER 1 + +timer_tick_rate_t timer_get_tick_rate(void) +{ + return tmrHw_getCountRate(PROF_TIMER); +} + +timer_tick_count_t timer_get_tick_count(void) +{ + return tmrHw_GetCurrentCount(PROF_TIMER); /* change downcounter to upcounter */ +} + +timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks) +{ + static int tickRateMsec; + + if (tickRateMsec == 0) { + tickRateMsec = timer_get_tick_rate() / 1000; + } + + return ticks / tickRateMsec; +} + +timer_msec_t timer_get_msec(void) +{ + return timer_ticks_to_msec(timer_get_tick_count()); +} + +EXPORT_SYMBOL(timer_get_tick_count); +EXPORT_SYMBOL(timer_ticks_to_msec); +EXPORT_SYMBOL(timer_get_tick_rate); +EXPORT_SYMBOL(timer_get_msec); -- GitLab From 16f5875034fa9e36a72c4223c8ef42cfe461d766 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:02:21 +0100 Subject: [PATCH 0980/1002] ARM: 5650/1: bcmring: add io.h, uncompress. h, and entry-macro.S add remaining header files in include/mach directory add entry-macro.S file Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../mach-bcmring/include/mach/entry-macro.S | 86 +++++++++++++++++++ arch/arm/mach-bcmring/include/mach/io.h | 56 ++++++++++++ .../mach-bcmring/include/mach/uncompress.h | 43 ++++++++++ 3 files changed, 185 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/entry-macro.S create mode 100644 arch/arm/mach-bcmring/include/mach/io.h create mode 100644 arch/arm/mach-bcmring/include/mach/uncompress.h diff --git a/arch/arm/mach-bcmring/include/mach/entry-macro.S b/arch/arm/mach-bcmring/include/mach/entry-macro.S new file mode 100644 index 0000000000000..7d393ca010acc --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/entry-macro.S @@ -0,0 +1,86 @@ +/***************************************************************************** +* Copyright 2006 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/* + * + * Low-level IRQ helper macros for BCMRing-based platforms + * + */ +#include <mach/irqs.h> +#include <mach/hardware.h> +#include <mach/csp/mm_io.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(MM_IO_BASE_INTC0) + ldr \irqstat, [\base, #0] @ get status + ldr \irqnr, [\base, #0x10] @ mask with enable register + ands \irqstat, \irqstat, \irqnr + mov \irqnr, #IRQ_INTC0_START + cmp \irqstat, #0 + bne 1001f + + ldr \base, =(MM_IO_BASE_INTC1) + ldr \irqstat, [\base, #0] @ get status + ldr \irqnr, [\base, #0x10] @ mask with enable register + ands \irqstat, \irqstat, \irqnr + mov \irqnr, #IRQ_INTC1_START + cmp \irqstat, #0 + bne 1001f + + ldr \base, =(MM_IO_BASE_SINTC) + ldr \irqstat, [\base, #0] @ get status + ldr \irqnr, [\base, #0x10] @ mask with enable register + ands \irqstat, \irqstat, \irqnr + mov \irqnr, #0xffffffff @ code meaning no interrupt bits set + cmp \irqstat, #0 + beq 1002f + + mov \irqnr, #IRQ_SINTC_START @ something is set, so fixup return value + +1001: + movs \tmp, \irqstat, lsl #16 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #16 + + movs \tmp, \irqstat, lsl #8 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #8 + + movs \tmp, \irqstat, lsl #4 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #4 + + movs \tmp, \irqstat, lsl #2 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #2 + + movs \tmp, \irqstat, lsl #1 + addeq \irqnr, \irqnr, #1 + orrs \base, \base, #1 + +1002: @ irqnr will be set to 0xffffffff if no irq bits are set + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro irq_prio_table + .endm + diff --git a/arch/arm/mach-bcmring/include/mach/io.h b/arch/arm/mach-bcmring/include/mach/io.h new file mode 100644 index 0000000000000..4db0eff90357f --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/io.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#include <mach/hardware.h> + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) ((void __iomem *)HW_IO_PHYS_TO_VIRT(a)) + +/* Do not enable mem_pci for a big endian arm architecture or unexpected byteswaps will */ +/* happen in readw/writew etc. */ + +#define readb(c) __raw_readb(c) +#define readw(c) __raw_readw(c) +#define readl(c) __raw_readl(c) +#define readb_relaxed(addr) readb(addr) +#define readw_relaxed(addr) readw(addr) +#define readl_relaxed(addr) readl(addr) + +#define readsb(p, d, l) __raw_readsb(p, d, l) +#define readsw(p, d, l) __raw_readsw(p, d, l) +#define readsl(p, d, l) __raw_readsl(p, d, l) + +#define writeb(v, c) __raw_writeb(v, c) +#define writew(v, c) __raw_writew(v, c) +#define writel(v, c) __raw_writel(v, c) + +#define writesb(p, d, l) __raw_writesb(p, d, l) +#define writesw(p, d, l) __raw_writesw(p, d, l) +#define writesl(p, d, l) __raw_writesl(p, d, l) + +#define memset_io(c, v, l) _memset_io((c), (v), (l)) +#define memcpy_fromio(a, c, l) _memcpy_fromio((a), (c), (l)) +#define memcpy_toio(c, a, l) _memcpy_toio((c), (a), (l)) + +#define eth_io_copy_and_sum(s, c, l, b) eth_copy_and_sum((s), (c), (l), (b)) + +#endif diff --git a/arch/arm/mach-bcmring/include/mach/uncompress.h b/arch/arm/mach-bcmring/include/mach/uncompress.h new file mode 100644 index 0000000000000..9c9821b779774 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/uncompress.h @@ -0,0 +1,43 @@ +/***************************************************************************** +* Copyright 2005 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ +#include <mach/csp/mm_addr.h> + +#define BCMRING_UART_0_DR (*(volatile unsigned int *)MM_ADDR_IO_UARTA) +#define BCMRING_UART_0_FR (*(volatile unsigned int *)(MM_ADDR_IO_UARTA + 0x18)) +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + /* Send out UARTA */ + while (BCMRING_UART_0_FR & (1 << 5)) + ; + + BCMRING_UART_0_DR = c; +} + + +static inline void flush(void) +{ + /* Wait for the tx fifo to be empty */ + while ((BCMRING_UART_0_FR & (1 << 7)) == 0) + ; + + /* Wait for the final character to be sent on the txd line */ + while (BCMRING_UART_0_FR & (1 << 3)) + ; +} + +#define arch_decomp_setup() +#define arch_decomp_wdog() -- GitLab From 7bab8bfc7f1060e3ab4bc0a90813a9338e6994b9 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:02:59 +0100 Subject: [PATCH 0981/1002] ARM: 5651/1: bcmring: csp capability header files add mach-bcmring csp capability header files Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/mach/csp/cap.h | 63 +++ .../include/mach/csp/cap_inline.h | 409 ++++++++++++++++++ .../mach-bcmring/include/mach/csp/hw_cfg.h | 73 ++++ 3 files changed, 545 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/csp/cap.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/cap_inline.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h diff --git a/arch/arm/mach-bcmring/include/mach/csp/cap.h b/arch/arm/mach-bcmring/include/mach/csp/cap.h new file mode 100644 index 0000000000000..30fa2d540630b --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/cap.h @@ -0,0 +1,63 @@ +/***************************************************************************** +* Copyright 2009 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CAP_H +#define CAP_H + +/* ---- Include Files ---------------------------------------------------- */ +/* ---- Public Constants and Types --------------------------------------- */ +typedef enum { + CAP_NOT_PRESENT = 0, + CAP_PRESENT +} CAP_RC_T; + +typedef enum { + CAP_VPM, + CAP_ETH_PHY, + CAP_ETH_GMII, + CAP_ETH_SGMII, + CAP_USB, + CAP_TSC, + CAP_EHSS, + CAP_SDIO, + CAP_UARTB, + CAP_KEYPAD, + CAP_CLCD, + CAP_GE, + CAP_LEDM, + CAP_BBL, + CAP_VDEC, + CAP_PIF, + CAP_APM, + CAP_SPU, + CAP_PKA, + CAP_RNG, +} CAP_CAPABILITY_T; + +typedef enum { + CAP_LCD_WVGA = 0, + CAP_LCD_VGA = 0x1, + CAP_LCD_WQVGA = 0x2, + CAP_LCD_QVGA = 0x3 +} CAP_LCD_RES_T; + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +static inline CAP_RC_T cap_isPresent(CAP_CAPABILITY_T capability, int index); +static inline uint32_t cap_getMaxArmSpeedHz(void); +static inline uint32_t cap_getMaxVpmSpeedHz(void); +static inline CAP_LCD_RES_T cap_getMaxLcdRes(void); + +#endif diff --git a/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h b/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h new file mode 100644 index 0000000000000..933ce68ed90b4 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h @@ -0,0 +1,409 @@ +/***************************************************************************** +* Copyright 2009 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CAP_INLINE_H +#define CAP_INLINE_H + +/* ---- Include Files ---------------------------------------------------- */ +#include <mach/csp/cap.h> +#include <cfg_global.h> + +/* ---- Public Constants and Types --------------------------------------- */ +#define CAP_CONFIG0_VPM_DIS 0x00000001 +#define CAP_CONFIG0_ETH_PHY0_DIS 0x00000002 +#define CAP_CONFIG0_ETH_PHY1_DIS 0x00000004 +#define CAP_CONFIG0_ETH_GMII0_DIS 0x00000008 +#define CAP_CONFIG0_ETH_GMII1_DIS 0x00000010 +#define CAP_CONFIG0_ETH_SGMII0_DIS 0x00000020 +#define CAP_CONFIG0_ETH_SGMII1_DIS 0x00000040 +#define CAP_CONFIG0_USB0_DIS 0x00000080 +#define CAP_CONFIG0_USB1_DIS 0x00000100 +#define CAP_CONFIG0_TSC_DIS 0x00000200 +#define CAP_CONFIG0_EHSS0_DIS 0x00000400 +#define CAP_CONFIG0_EHSS1_DIS 0x00000800 +#define CAP_CONFIG0_SDIO0_DIS 0x00001000 +#define CAP_CONFIG0_SDIO1_DIS 0x00002000 +#define CAP_CONFIG0_UARTB_DIS 0x00004000 +#define CAP_CONFIG0_KEYPAD_DIS 0x00008000 +#define CAP_CONFIG0_CLCD_DIS 0x00010000 +#define CAP_CONFIG0_GE_DIS 0x00020000 +#define CAP_CONFIG0_LEDM_DIS 0x00040000 +#define CAP_CONFIG0_BBL_DIS 0x00080000 +#define CAP_CONFIG0_VDEC_DIS 0x00100000 +#define CAP_CONFIG0_PIF_DIS 0x00200000 +#define CAP_CONFIG0_RESERVED1_DIS 0x00400000 +#define CAP_CONFIG0_RESERVED2_DIS 0x00800000 + +#define CAP_CONFIG1_APMA_DIS 0x00000001 +#define CAP_CONFIG1_APMB_DIS 0x00000002 +#define CAP_CONFIG1_APMC_DIS 0x00000004 +#define CAP_CONFIG1_CLCD_RES_MASK 0x00000600 +#define CAP_CONFIG1_CLCD_RES_SHIFT 9 +#define CAP_CONFIG1_CLCD_RES_WVGA (CAP_LCD_WVGA << CAP_CONFIG1_CLCD_RES_SHIFT) +#define CAP_CONFIG1_CLCD_RES_VGA (CAP_LCD_VGA << CAP_CONFIG1_CLCD_RES_SHIFT) +#define CAP_CONFIG1_CLCD_RES_WQVGA (CAP_LCD_WQVGA << CAP_CONFIG1_CLCD_RES_SHIFT) +#define CAP_CONFIG1_CLCD_RES_QVGA (CAP_LCD_QVGA << CAP_CONFIG1_CLCD_RES_SHIFT) + +#define CAP_CONFIG2_SPU_DIS 0x00000010 +#define CAP_CONFIG2_PKA_DIS 0x00000020 +#define CAP_CONFIG2_RNG_DIS 0x00000080 + +#if (CFG_GLOBAL_CHIP == BCM11107) +#define capConfig0 0 +#define capConfig1 CAP_CONFIG1_CLCD_RES_WVGA +#define capConfig2 0 +#define CAP_APM_MAX_NUM_CHANS 3 +#elif (CFG_GLOBAL_CHIP == FPGA11107) +#define capConfig0 0 +#define capConfig1 CAP_CONFIG1_CLCD_RES_WVGA +#define capConfig2 0 +#define CAP_APM_MAX_NUM_CHANS 3 +#elif (CFG_GLOBAL_CHIP == BCM11109) +#define capConfig0 (CAP_CONFIG0_USB1_DIS | CAP_CONFIG0_EHSS1_DIS | CAP_CONFIG0_SDIO1_DIS | CAP_CONFIG0_GE_DIS | CAP_CONFIG0_BBL_DIS | CAP_CONFIG0_VDEC_DIS) +#define capConfig1 (CAP_CONFIG1_APMC_DIS | CAP_CONFIG1_CLCD_RES_WQVGA) +#define capConfig2 (CAP_CONFIG2_SPU_DIS | CAP_CONFIG2_PKA_DIS) +#define CAP_APM_MAX_NUM_CHANS 2 +#elif (CFG_GLOBAL_CHIP == BCM11170) +#define capConfig0 (CAP_CONFIG0_ETH_GMII0_DIS | CAP_CONFIG0_ETH_GMII1_DIS | CAP_CONFIG0_USB0_DIS | CAP_CONFIG0_USB1_DIS | CAP_CONFIG0_TSC_DIS | CAP_CONFIG0_EHSS1_DIS | CAP_CONFIG0_SDIO0_DIS | CAP_CONFIG0_SDIO1_DIS | CAP_CONFIG0_UARTB_DIS | CAP_CONFIG0_CLCD_DIS | CAP_CONFIG0_GE_DIS | CAP_CONFIG0_BBL_DIS | CAP_CONFIG0_VDEC_DIS) +#define capConfig1 (CAP_CONFIG1_APMC_DIS | CAP_CONFIG1_CLCD_RES_WQVGA) +#define capConfig2 (CAP_CONFIG2_SPU_DIS | CAP_CONFIG2_PKA_DIS) +#define CAP_APM_MAX_NUM_CHANS 2 +#elif (CFG_GLOBAL_CHIP == BCM11110) +#define capConfig0 (CAP_CONFIG0_USB1_DIS | CAP_CONFIG0_TSC_DIS | CAP_CONFIG0_EHSS1_DIS | CAP_CONFIG0_SDIO0_DIS | CAP_CONFIG0_SDIO1_DIS | CAP_CONFIG0_UARTB_DIS | CAP_CONFIG0_GE_DIS | CAP_CONFIG0_BBL_DIS | CAP_CONFIG0_VDEC_DIS) +#define capConfig1 CAP_CONFIG1_APMC_DIS +#define capConfig2 (CAP_CONFIG2_SPU_DIS | CAP_CONFIG2_PKA_DIS) +#define CAP_APM_MAX_NUM_CHANS 2 +#elif (CFG_GLOBAL_CHIP == BCM11211) +#define capConfig0 (CAP_CONFIG0_ETH_PHY0_DIS | CAP_CONFIG0_ETH_GMII0_DIS | CAP_CONFIG0_ETH_GMII1_DIS | CAP_CONFIG0_ETH_SGMII0_DIS | CAP_CONFIG0_ETH_SGMII1_DIS | CAP_CONFIG0_CLCD_DIS) +#define capConfig1 CAP_CONFIG1_APMC_DIS +#define capConfig2 0 +#define CAP_APM_MAX_NUM_CHANS 2 +#else +#error CFG_GLOBAL_CHIP type capabilities not defined +#endif + +#if ((CFG_GLOBAL_CHIP == BCM11107) || (CFG_GLOBAL_CHIP == FPGA11107)) +#define CAP_HW_CFG_ARM_CLK_HZ 500000000 +#elif ((CFG_GLOBAL_CHIP == BCM11109) || (CFG_GLOBAL_CHIP == BCM11170) || (CFG_GLOBAL_CHIP == BCM11110)) +#define CAP_HW_CFG_ARM_CLK_HZ 300000000 +#elif (CFG_GLOBAL_CHIP == BCM11211) +#define CAP_HW_CFG_ARM_CLK_HZ 666666666 +#else +#error CFG_GLOBAL_CHIP type capabilities not defined +#endif + +#if ((CFG_GLOBAL_CHIP == BCM11107) || (CFG_GLOBAL_CHIP == BCM11211) || (CFG_GLOBAL_CHIP == FPGA11107)) +#define CAP_HW_CFG_VPM_CLK_HZ 333333333 +#elif ((CFG_GLOBAL_CHIP == BCM11109) || (CFG_GLOBAL_CHIP == BCM11170) || (CFG_GLOBAL_CHIP == BCM11110)) +#define CAP_HW_CFG_VPM_CLK_HZ 200000000 +#else +#error CFG_GLOBAL_CHIP type capabilities not defined +#endif + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +/**************************************************************************** +* cap_isPresent - +* +* PURPOSE: +* Determines if the chip has a certain capability present +* +* PARAMETERS: +* capability - type of capability to determine if present +* +* RETURNS: +* CAP_PRESENT or CAP_NOT_PRESENT +****************************************************************************/ +static inline CAP_RC_T cap_isPresent(CAP_CAPABILITY_T capability, int index) +{ + CAP_RC_T returnVal = CAP_NOT_PRESENT; + + switch (capability) { + case CAP_VPM: + { + if (!(capConfig0 & CAP_CONFIG0_VPM_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_ETH_PHY: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_ETH_PHY0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_ETH_PHY1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_ETH_GMII: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_ETH_GMII0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_ETH_GMII1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_ETH_SGMII: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_ETH_SGMII0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_ETH_SGMII1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_USB: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_USB0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_USB1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_TSC: + { + if (!(capConfig0 & CAP_CONFIG0_TSC_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_EHSS: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_EHSS0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_EHSS1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_SDIO: + { + if ((index == 0) + && (!(capConfig0 & CAP_CONFIG0_SDIO0_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig0 & CAP_CONFIG0_SDIO1_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_UARTB: + { + if (!(capConfig0 & CAP_CONFIG0_UARTB_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_KEYPAD: + { + if (!(capConfig0 & CAP_CONFIG0_KEYPAD_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_CLCD: + { + if (!(capConfig0 & CAP_CONFIG0_CLCD_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_GE: + { + if (!(capConfig0 & CAP_CONFIG0_GE_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_LEDM: + { + if (!(capConfig0 & CAP_CONFIG0_LEDM_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_BBL: + { + if (!(capConfig0 & CAP_CONFIG0_BBL_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_VDEC: + { + if (!(capConfig0 & CAP_CONFIG0_VDEC_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_PIF: + { + if (!(capConfig0 & CAP_CONFIG0_PIF_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_APM: + { + if ((index == 0) + && (!(capConfig1 & CAP_CONFIG1_APMA_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 1) + && (!(capConfig1 & CAP_CONFIG1_APMB_DIS))) { + returnVal = CAP_PRESENT; + } + if ((index == 2) + && (!(capConfig1 & CAP_CONFIG1_APMC_DIS))) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_SPU: + { + if (!(capConfig2 & CAP_CONFIG2_SPU_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_PKA: + { + if (!(capConfig2 & CAP_CONFIG2_PKA_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + case CAP_RNG: + { + if (!(capConfig2 & CAP_CONFIG2_RNG_DIS)) { + returnVal = CAP_PRESENT; + } + } + break; + + default: + { + } + break; + } + return returnVal; +} + +/**************************************************************************** +* cap_getMaxArmSpeedHz - +* +* PURPOSE: +* Determines the maximum speed of the ARM CPU +* +* PARAMETERS: +* none +* +* RETURNS: +* clock speed in Hz that the ARM processor is able to run at +****************************************************************************/ +static inline uint32_t cap_getMaxArmSpeedHz(void) +{ +#if ((CFG_GLOBAL_CHIP == BCM11107) || (CFG_GLOBAL_CHIP == FPGA11107)) + return 500000000; +#elif ((CFG_GLOBAL_CHIP == BCM11109) || (CFG_GLOBAL_CHIP == BCM11170) || (CFG_GLOBAL_CHIP == BCM11110)) + return 300000000; +#elif (CFG_GLOBAL_CHIP == BCM11211) + return 666666666; +#else +#error CFG_GLOBAL_CHIP type capabilities not defined +#endif +} + +/**************************************************************************** +* cap_getMaxVpmSpeedHz - +* +* PURPOSE: +* Determines the maximum speed of the VPM +* +* PARAMETERS: +* none +* +* RETURNS: +* clock speed in Hz that the VPM is able to run at +****************************************************************************/ +static inline uint32_t cap_getMaxVpmSpeedHz(void) +{ +#if ((CFG_GLOBAL_CHIP == BCM11107) || (CFG_GLOBAL_CHIP == BCM11211) || (CFG_GLOBAL_CHIP == FPGA11107)) + return 333333333; +#elif ((CFG_GLOBAL_CHIP == BCM11109) || (CFG_GLOBAL_CHIP == BCM11170) || (CFG_GLOBAL_CHIP == BCM11110)) + return 200000000; +#else +#error CFG_GLOBAL_CHIP type capabilities not defined +#endif +} + +/**************************************************************************** +* cap_getMaxLcdRes - +* +* PURPOSE: +* Determines the maximum LCD resolution capabilities +* +* PARAMETERS: +* none +* +* RETURNS: +* CAP_LCD_WVGA, CAP_LCD_VGA, CAP_LCD_WQVGA or CAP_LCD_QVGA +* +****************************************************************************/ +static inline CAP_LCD_RES_T cap_getMaxLcdRes(void) +{ + return (CAP_LCD_RES_T) + ((capConfig1 & CAP_CONFIG1_CLCD_RES_MASK) >> + CAP_CONFIG1_CLCD_RES_SHIFT); +} + +#endif diff --git a/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h b/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h new file mode 100644 index 0000000000000..cfa91bed9d347 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h @@ -0,0 +1,73 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + + +#ifndef CSP_HW_CFG_H +#define CSP_HW_CFG_H + +/* ---- Include Files ---------------------------------------------------- */ + +#include <cfg_global.h> +#include <mach/csp/cap_inline.h> + +#if defined(__KERNEL__) +#include <mach/memory_settings.h> +#else +#include <hw_cfg.h> +#endif + +/* Some items that can be defined externally, but will be set to default values */ +/* if they are not defined. */ +/* HW_CFG_PLL_SPREAD_SPECTRUM_DISABLE Default undefined and SS is enabled. */ +/* HW_CFG_SDRAM_CAS_LATENCY 5 Default 5, Values [3..6] */ +/* HW_CFG_SDRAM_CHIP_SELECT_CNT 1 Default 1, Vaules [1..2] */ +/* HW_CFG_SDRAM_SPEED_GRADE 667 Default 667, Values [400,533,667,800] */ +/* HW_CFG_SDRAM_WIDTH_BITS 16 Default 16, Vaules [8,16] */ +/* HW_CFG_SDRAM_ADDR_BRC Default undefined and Row-Bank-Col (RBC) addressing used. Define to use Bank-Row-Col (BRC). */ +/* HW_CFG_SDRAM_CLK_ASYNC Default undefined and DDR clock is synchronous with AXI BUS clock. Define for ASYNC mode. */ + +#if defined(CFG_GLOBAL_CHIP) + #if (CFG_GLOBAL_CHIP == FPGA11107) + #define HW_CFG_BUS_CLK_HZ 5000000 + #define HW_CFG_DDR_CTLR_CLK_HZ 10000000 + #define HW_CFG_DDR_PHY_OMIT + #define HW_CFG_UART_CLK_HZ 7500000 + #else + #define HW_CFG_PLL_VCO_HZ 2000000000 + #define HW_CFG_PLL2_VCO_HZ 1800000000 + #define HW_CFG_ARM_CLK_HZ CAP_HW_CFG_ARM_CLK_HZ + #define HW_CFG_BUS_CLK_HZ 166666666 + #define HW_CFG_DDR_CTLR_CLK_HZ 333333333 + #define HW_CFG_DDR_PHY_CLK_HZ (2 * HW_CFG_DDR_CTLR_CLK_HZ) + #define HW_CFG_UART_CLK_HZ 142857142 + #define HW_CFG_VPM_CLK_HZ CAP_HW_CFG_VPM_CLK_HZ + #endif +#else + #define HW_CFG_PLL_VCO_HZ 1800000000 + #define HW_CFG_PLL2_VCO_HZ 1800000000 + #define HW_CFG_ARM_CLK_HZ 450000000 + #define HW_CFG_BUS_CLK_HZ 150000000 + #define HW_CFG_DDR_CTLR_CLK_HZ 300000000 + #define HW_CFG_DDR_PHY_CLK_HZ (2 * HW_CFG_DDR_CTLR_CLK_HZ) + #define HW_CFG_UART_CLK_HZ 150000000 + #define HW_CFG_VPM_CLK_HZ 300000000 +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + + +#endif /* CSP_HW_CFG_H */ + -- GitLab From 9133760f4b0c0628d45532aad17f59896cd7b57f Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:03:40 +0100 Subject: [PATCH 0982/1002] ARM: 5652/1: bcmring: add misc headers for csp code add misc wrapper headers for csp code add ddrc register header file Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/csp/cache.h | 35 + arch/arm/mach-bcmring/include/csp/delay.h | 36 + arch/arm/mach-bcmring/include/csp/errno.h | 32 + arch/arm/mach-bcmring/include/csp/module.h | 32 + arch/arm/mach-bcmring/include/csp/reg.h | 114 +++ arch/arm/mach-bcmring/include/csp/stdint.h | 30 + arch/arm/mach-bcmring/include/csp/string.h | 34 + .../mach-bcmring/include/mach/csp/ddrcReg.h | 872 ++++++++++++++++++ 8 files changed, 1185 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/csp/cache.h create mode 100644 arch/arm/mach-bcmring/include/csp/delay.h create mode 100644 arch/arm/mach-bcmring/include/csp/errno.h create mode 100644 arch/arm/mach-bcmring/include/csp/module.h create mode 100644 arch/arm/mach-bcmring/include/csp/reg.h create mode 100644 arch/arm/mach-bcmring/include/csp/stdint.h create mode 100644 arch/arm/mach-bcmring/include/csp/string.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h diff --git a/arch/arm/mach-bcmring/include/csp/cache.h b/arch/arm/mach-bcmring/include/csp/cache.h new file mode 100644 index 0000000000000..caa20e59db99a --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/cache.h @@ -0,0 +1,35 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CSP_CACHE_H +#define CSP_CACHE_H + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/stdint.h> + +/* ---- Public Constants and Types --------------------------------------- */ + +#if defined(__KERNEL__) && !defined(STANDALONE) +#include <asm/cacheflush.h> + +#define CSP_CACHE_FLUSH_ALL flush_cache_all() + +#else + +#define CSP_CACHE_FLUSH_ALL + +#endif + +#endif /* CSP_CACHE_H */ diff --git a/arch/arm/mach-bcmring/include/csp/delay.h b/arch/arm/mach-bcmring/include/csp/delay.h new file mode 100644 index 0000000000000..8b3d803672938 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/delay.h @@ -0,0 +1,36 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + + +#ifndef CSP_DELAY_H +#define CSP_DELAY_H + +/* ---- Include Files ---------------------------------------------------- */ + +/* Some CSP routines require use of the following delay routines. Use the OS */ +/* version if available, otherwise use a CSP specific definition. */ +/* void udelay(unsigned long usecs); */ +/* void mdelay(unsigned long msecs); */ + +#if defined(__KERNEL__) && !defined(STANDALONE) + #include <linux/delay.h> +#else + #include <mach/csp/delay.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +#endif /* CSP_DELAY_H */ diff --git a/arch/arm/mach-bcmring/include/csp/errno.h b/arch/arm/mach-bcmring/include/csp/errno.h new file mode 100644 index 0000000000000..51357dd5b6667 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/errno.h @@ -0,0 +1,32 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CSP_ERRNO_H +#define CSP_ERRNO_H + +/* ---- Include Files ---------------------------------------------------- */ + +#if defined(__KERNEL__) +#include <linux/errno.h> +#elif defined(CSP_SIMULATION) +#include <asm-generic/errno.h> +#else +#include <errno.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +#endif /* CSP_ERRNO_H */ diff --git a/arch/arm/mach-bcmring/include/csp/module.h b/arch/arm/mach-bcmring/include/csp/module.h new file mode 100644 index 0000000000000..c30d2a5975a69 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/module.h @@ -0,0 +1,32 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + + +#ifndef CSP_MODULE_H +#define CSP_MODULE_H + +/* ---- Include Files ---------------------------------------------------- */ + +#ifdef __KERNEL__ + #include <linux/module.h> +#else + #define EXPORT_SYMBOL(symbol) +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + + +#endif /* CSP_MODULE_H */ diff --git a/arch/arm/mach-bcmring/include/csp/reg.h b/arch/arm/mach-bcmring/include/csp/reg.h new file mode 100644 index 0000000000000..e5f60bf5a1f3c --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/reg.h @@ -0,0 +1,114 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file reg.h +* +* @brief Generic register defintions used in CSP +*/ +/****************************************************************************/ + +#ifndef CSP_REG_H +#define CSP_REG_H + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/stdint.h> + +/* ---- Public Constants and Types --------------------------------------- */ + +#define __REG32(x) (*((volatile uint32_t *)(x))) +#define __REG16(x) (*((volatile uint16_t *)(x))) +#define __REG8(x) (*((volatile uint8_t *) (x))) + +/* Macros used to define a sequence of reserved registers. The start / end */ +/* are byte offsets in the particular register definition, with the "end" */ +/* being the offset of the next un-reserved register. E.g. if offsets */ +/* 0x10 through to 0x1f are reserved, then this reserved area could be */ +/* specified as follows. */ +/* typedef struct */ +/* { */ +/* uint32_t reg1; offset 0x00 */ +/* uint32_t reg2; offset 0x04 */ +/* uint32_t reg3; offset 0x08 */ +/* uint32_t reg4; offset 0x0c */ +/* REG32_RSVD(0x10, 0x20); */ +/* uint32_t reg5; offset 0x20 */ +/* ... */ +/* } EXAMPLE_REG_t; */ +#define REG8_RSVD(start, end) uint8_t rsvd_##start[(end - start) / sizeof(uint8_t)] +#define REG16_RSVD(start, end) uint16_t rsvd_##start[(end - start) / sizeof(uint16_t)] +#define REG32_RSVD(start, end) uint32_t rsvd_##start[(end - start) / sizeof(uint32_t)] + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +/* Note: When protecting multiple statements, the REG_LOCAL_IRQ_SAVE and */ +/* REG_LOCAL_IRQ_RESTORE must be enclosed in { } to allow the */ +/* flags variable to be declared locally. */ +/* e.g. */ +/* statement1; */ +/* { */ +/* REG_LOCAL_IRQ_SAVE; */ +/* <multiple statements here> */ +/* REG_LOCAL_IRQ_RESTORE; */ +/* } */ +/* statement2; */ +/* */ + +#if defined(__KERNEL__) && !defined(STANDALONE) +#include <mach/hardware.h> +#include <linux/interrupt.h> + +#define REG_LOCAL_IRQ_SAVE HW_DECLARE_SPINLOCK(reg32) \ + unsigned long flags; HW_IRQ_SAVE(reg32, flags) + +#define REG_LOCAL_IRQ_RESTORE HW_IRQ_RESTORE(reg32, flags) + +#else + +#define REG_LOCAL_IRQ_SAVE +#define REG_LOCAL_IRQ_RESTORE + +#endif + +static inline void reg32_modify_and(volatile uint32_t *reg, uint32_t value) +{ + REG_LOCAL_IRQ_SAVE; + *reg &= value; + REG_LOCAL_IRQ_RESTORE; +} + +static inline void reg32_modify_or(volatile uint32_t *reg, uint32_t value) +{ + REG_LOCAL_IRQ_SAVE; + *reg |= value; + REG_LOCAL_IRQ_RESTORE; +} + +static inline void reg32_modify_mask(volatile uint32_t *reg, uint32_t mask, + uint32_t value) +{ + REG_LOCAL_IRQ_SAVE; + *reg = (*reg & mask) | value; + REG_LOCAL_IRQ_RESTORE; +} + +static inline void reg32_write(volatile uint32_t *reg, uint32_t value) +{ + *reg = value; +} + +#endif /* CSP_REG_H */ diff --git a/arch/arm/mach-bcmring/include/csp/stdint.h b/arch/arm/mach-bcmring/include/csp/stdint.h new file mode 100644 index 0000000000000..3a8718bbf7009 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/stdint.h @@ -0,0 +1,30 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CSP_STDINT_H +#define CSP_STDINT_H + +/* ---- Include Files ---------------------------------------------------- */ + +#ifdef __KERNEL__ +#include <linux/types.h> +#else +#include <stdint.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +#endif /* CSP_STDINT_H */ diff --git a/arch/arm/mach-bcmring/include/csp/string.h b/arch/arm/mach-bcmring/include/csp/string.h new file mode 100644 index 0000000000000..ad9e4005f1417 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/string.h @@ -0,0 +1,34 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + + + +#ifndef CSP_STRING_H +#define CSP_STRING_H + +/* ---- Include Files ---------------------------------------------------- */ + +#ifdef __KERNEL__ + #include <linux/string.h> +#else + #include <string.h> +#endif + +/* ---- Public Constants and Types --------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + + +#endif /* CSP_STRING_H */ + diff --git a/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h b/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h new file mode 100644 index 0000000000000..f1b68e26fa6de --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h @@ -0,0 +1,872 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file ddrcReg.h +* +* @brief Register definitions for BCMRING DDR2 Controller and PHY +* +*/ +/****************************************************************************/ + +#ifndef DDRC_REG_H +#define DDRC_REG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/reg.h> +#include <csp/stdint.h> + +#include <mach/csp/mm_io.h> + +/* ---- Public Constants and Types --------------------------------------- */ + +/*********************************************************************/ +/* DDR2 Controller (ARM PL341) register definitions */ +/*********************************************************************/ + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* ARM PL341 DDR2 configuration registers, offset 0x000 */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + + typedef struct { + uint32_t memcStatus; + uint32_t memcCmd; + uint32_t directCmd; + uint32_t memoryCfg; + uint32_t refreshPrd; + uint32_t casLatency; + uint32_t writeLatency; + uint32_t tMrd; + uint32_t tRas; + uint32_t tRc; + uint32_t tRcd; + uint32_t tRfc; + uint32_t tRp; + uint32_t tRrd; + uint32_t tWr; + uint32_t tWtr; + uint32_t tXp; + uint32_t tXsr; + uint32_t tEsr; + uint32_t memoryCfg2; + uint32_t memoryCfg3; + uint32_t tFaw; + } ddrcReg_CTLR_MEMC_REG_t; + +#define ddrcReg_CTLR_MEMC_REG_OFFSET 0x0000 +#define ddrcReg_CTLR_MEMC_REGP ((volatile ddrcReg_CTLR_MEMC_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_CTLR_MEMC_REG_OFFSET)) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_MEMC_STATUS_BANKS_MASK (0x3 << 12) +#define ddrcReg_CTLR_MEMC_STATUS_BANKS_4 (0x0 << 12) +#define ddrcReg_CTLR_MEMC_STATUS_BANKS_8 (0x3 << 12) + +#define ddrcReg_CTLR_MEMC_STATUS_MONITORS_MASK (0x3 << 10) +#define ddrcReg_CTLR_MEMC_STATUS_MONITORS_0 (0x0 << 10) +#define ddrcReg_CTLR_MEMC_STATUS_MONITORS_1 (0x1 << 10) +#define ddrcReg_CTLR_MEMC_STATUS_MONITORS_2 (0x2 << 10) +#define ddrcReg_CTLR_MEMC_STATUS_MONITORS_4 (0x3 << 10) + +#define ddrcReg_CTLR_MEMC_STATUS_CHIPS_MASK (0x3 << 7) +#define ddrcReg_CTLR_MEMC_STATUS_CHIPS_1 (0x0 << 7) +#define ddrcReg_CTLR_MEMC_STATUS_CHIPS_2 (0x1 << 7) +#define ddrcReg_CTLR_MEMC_STATUS_CHIPS_3 (0x2 << 7) +#define ddrcReg_CTLR_MEMC_STATUS_CHIPS_4 (0x3 << 7) + +#define ddrcReg_CTLR_MEMC_STATUS_TYPE_MASK (0x7 << 4) +#define ddrcReg_CTLR_MEMC_STATUS_TYPE_DDR2 (0x5 << 4) + +#define ddrcReg_CTLR_MEMC_STATUS_WIDTH_MASK (0x3 << 2) +#define ddrcReg_CTLR_MEMC_STATUS_WIDTH_16 (0x0 << 2) +#define ddrcReg_CTLR_MEMC_STATUS_WIDTH_32 (0x1 << 2) +#define ddrcReg_CTLR_MEMC_STATUS_WIDTH_64 (0x2 << 2) +#define ddrcReg_CTLR_MEMC_STATUS_WIDTH_128 (0x3 << 2) + +#define ddrcReg_CTLR_MEMC_STATUS_STATE_MASK (0x3 << 0) +#define ddrcReg_CTLR_MEMC_STATUS_STATE_CONFIG (0x0 << 0) +#define ddrcReg_CTLR_MEMC_STATUS_STATE_READY (0x1 << 0) +#define ddrcReg_CTLR_MEMC_STATUS_STATE_PAUSED (0x2 << 0) +#define ddrcReg_CTLR_MEMC_STATUS_STATE_LOWPWR (0x3 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_MEMC_CMD_MASK (0x7 << 0) +#define ddrcReg_CTLR_MEMC_CMD_GO (0x0 << 0) +#define ddrcReg_CTLR_MEMC_CMD_SLEEP (0x1 << 0) +#define ddrcReg_CTLR_MEMC_CMD_WAKEUP (0x2 << 0) +#define ddrcReg_CTLR_MEMC_CMD_PAUSE (0x3 << 0) +#define ddrcReg_CTLR_MEMC_CMD_CONFIGURE (0x4 << 0) +#define ddrcReg_CTLR_MEMC_CMD_ACTIVE_PAUSE (0x7 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_DIRECT_CMD_CHIP_SHIFT 20 +#define ddrcReg_CTLR_DIRECT_CMD_CHIP_MASK (0x3 << ddrcReg_CTLR_DIRECT_CMD_CHIP_SHIFT) + +#define ddrcReg_CTLR_DIRECT_CMD_TYPE_PRECHARGEALL (0x0 << 18) +#define ddrcReg_CTLR_DIRECT_CMD_TYPE_AUTOREFRESH (0x1 << 18) +#define ddrcReg_CTLR_DIRECT_CMD_TYPE_MODEREG (0x2 << 18) +#define ddrcReg_CTLR_DIRECT_CMD_TYPE_NOP (0x3 << 18) + +#define ddrcReg_CTLR_DIRECT_CMD_BANK_SHIFT 16 +#define ddrcReg_CTLR_DIRECT_CMD_BANK_MASK (0x3 << ddrcReg_CTLR_DIRECT_CMD_BANK_SHIFT) + +#define ddrcReg_CTLR_DIRECT_CMD_ADDR_SHIFT 0 +#define ddrcReg_CTLR_DIRECT_CMD_ADDR_MASK (0x1ffff << ddrcReg_CTLR_DIRECT_CMD_ADDR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_MEMORY_CFG_CHIP_CNT_MASK (0x3 << 21) +#define ddrcReg_CTLR_MEMORY_CFG_CHIP_CNT_1 (0x0 << 21) +#define ddrcReg_CTLR_MEMORY_CFG_CHIP_CNT_2 (0x1 << 21) +#define ddrcReg_CTLR_MEMORY_CFG_CHIP_CNT_3 (0x2 << 21) +#define ddrcReg_CTLR_MEMORY_CFG_CHIP_CNT_4 (0x3 << 21) + +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_MASK (0x7 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_3_0 (0x0 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_4_1 (0x1 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_5_2 (0x2 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_6_3 (0x3 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_7_4 (0x4 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_8_5 (0x5 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_9_6 (0x6 << 18) +#define ddrcReg_CTLR_MEMORY_CFG_QOS_ARID_10_7 (0x7 << 18) + +#define ddrcReg_CTLR_MEMORY_CFG_BURST_LEN_MASK (0x7 << 15) +#define ddrcReg_CTLR_MEMORY_CFG_BURST_LEN_4 (0x2 << 15) +#define ddrcReg_CTLR_MEMORY_CFG_BURST_LEN_8 (0x3 << 15) /* @note Not supported in PL341 */ + +#define ddrcReg_CTLR_MEMORY_CFG_PWRDOWN_ENABLE (0x1 << 13) + +#define ddrcReg_CTLR_MEMORY_CFG_PWRDOWN_CYCLES_SHIFT 7 +#define ddrcReg_CTLR_MEMORY_CFG_PWRDOWN_CYCLES_MASK (0x3f << ddrcReg_CTLR_MEMORY_CFG_PWRDOWN_CYCLES_SHIFT) + +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_MASK (0x7 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_11 (0x0 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_12 (0x1 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_13 (0x2 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_14 (0x3 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_15 (0x4 << 3) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_ROW_BITS_16 (0x5 << 3) + +#define ddrcReg_CTLR_MEMORY_CFG_AXI_COL_BITS_MASK (0x7 << 0) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_COL_BITS_9 (0x1 << 0) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_COL_BITS_10 (0x2 << 0) +#define ddrcReg_CTLR_MEMORY_CFG_AXI_COL_BITS_11 (0x3 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_REFRESH_PRD_SHIFT 0 +#define ddrcReg_CTLR_REFRESH_PRD_MASK (0x7fff << ddrcReg_CTLR_REFRESH_PRD_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_CAS_LATENCY_SHIFT 1 +#define ddrcReg_CTLR_CAS_LATENCY_MASK (0x7 << ddrcReg_CTLR_CAS_LATENCY_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_WRITE_LATENCY_SHIFT 0 +#define ddrcReg_CTLR_WRITE_LATENCY_MASK (0x7 << ddrcReg_CTLR_WRITE_LATENCY_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_MRD_SHIFT 0 +#define ddrcReg_CTLR_T_MRD_MASK (0x7f << ddrcReg_CTLR_T_MRD_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RAS_SHIFT 0 +#define ddrcReg_CTLR_T_RAS_MASK (0x1f << ddrcReg_CTLR_T_RAS_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RC_SHIFT 0 +#define ddrcReg_CTLR_T_RC_MASK (0x1f << ddrcReg_CTLR_T_RC_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RCD_SCHEDULE_DELAY_SHIFT 8 +#define ddrcReg_CTLR_T_RCD_SCHEDULE_DELAY_MASK (0x7 << ddrcReg_CTLR_T_RCD_SCHEDULE_DELAY_SHIFT) + +#define ddrcReg_CTLR_T_RCD_SHIFT 0 +#define ddrcReg_CTLR_T_RCD_MASK (0x7 << ddrcReg_CTLR_T_RCD_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RFC_SCHEDULE_DELAY_SHIFT 8 +#define ddrcReg_CTLR_T_RFC_SCHEDULE_DELAY_MASK (0x7f << ddrcReg_CTLR_T_RFC_SCHEDULE_DELAY_SHIFT) + +#define ddrcReg_CTLR_T_RFC_SHIFT 0 +#define ddrcReg_CTLR_T_RFC_MASK (0x7f << ddrcReg_CTLR_T_RFC_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RP_SCHEDULE_DELAY_SHIFT 8 +#define ddrcReg_CTLR_T_RP_SCHEDULE_DELAY_MASK (0x7 << ddrcReg_CTLR_T_RP_SCHEDULE_DELAY_SHIFT) + +#define ddrcReg_CTLR_T_RP_SHIFT 0 +#define ddrcReg_CTLR_T_RP_MASK (0xf << ddrcReg_CTLR_T_RP_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_RRD_SHIFT 0 +#define ddrcReg_CTLR_T_RRD_MASK (0xf << ddrcReg_CTLR_T_RRD_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_WR_SHIFT 0 +#define ddrcReg_CTLR_T_WR_MASK (0x7 << ddrcReg_CTLR_T_WR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_WTR_SHIFT 0 +#define ddrcReg_CTLR_T_WTR_MASK (0x7 << ddrcReg_CTLR_T_WTR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_XP_SHIFT 0 +#define ddrcReg_CTLR_T_XP_MASK (0xff << ddrcReg_CTLR_T_XP_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_XSR_SHIFT 0 +#define ddrcReg_CTLR_T_XSR_MASK (0xff << ddrcReg_CTLR_T_XSR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_ESR_SHIFT 0 +#define ddrcReg_CTLR_T_ESR_MASK (0xff << ddrcReg_CTLR_T_ESR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_MEMORY_CFG2_WIDTH_MASK (0x3 << 6) +#define ddrcReg_CTLR_MEMORY_CFG2_WIDTH_16BITS (0 << 6) +#define ddrcReg_CTLR_MEMORY_CFG2_WIDTH_32BITS (1 << 6) +#define ddrcReg_CTLR_MEMORY_CFG2_WIDTH_64BITS (2 << 6) + +#define ddrcReg_CTLR_MEMORY_CFG2_AXI_BANK_BITS_MASK (0x3 << 4) +#define ddrcReg_CTLR_MEMORY_CFG2_AXI_BANK_BITS_2 (0 << 4) +#define ddrcReg_CTLR_MEMORY_CFG2_AXI_BANK_BITS_3 (3 << 4) + +#define ddrcReg_CTLR_MEMORY_CFG2_CKE_INIT_STATE_LOW (0 << 3) +#define ddrcReg_CTLR_MEMORY_CFG2_CKE_INIT_STATE_HIGH (1 << 3) + +#define ddrcReg_CTLR_MEMORY_CFG2_DQM_INIT_STATE_LOW (0 << 2) +#define ddrcReg_CTLR_MEMORY_CFG2_DQM_INIT_STATE_HIGH (1 << 2) + +#define ddrcReg_CTLR_MEMORY_CFG2_CLK_MASK (0x3 << 0) +#define ddrcReg_CTLR_MEMORY_CFG2_CLK_ASYNC (0 << 0) +#define ddrcReg_CTLR_MEMORY_CFG2_CLK_SYNC_A_LE_M (1 << 0) +#define ddrcReg_CTLR_MEMORY_CFG2_CLK_SYNC_A_GT_M (3 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_MEMORY_CFG3_REFRESH_TO_SHIFT 0 +#define ddrcReg_CTLR_MEMORY_CFG3_REFRESH_TO_MASK (0x7 << ddrcReg_CTLR_MEMORY_CFG3_REFRESH_TO_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_T_FAW_SCHEDULE_DELAY_SHIFT 8 +#define ddrcReg_CTLR_T_FAW_SCHEDULE_DELAY_MASK (0x1f << ddrcReg_CTLR_T_FAW_SCHEDULE_DELAY_SHIFT) + +#define ddrcReg_CTLR_T_FAW_PERIOD_SHIFT 0 +#define ddrcReg_CTLR_T_FAW_PERIOD_MASK (0x1f << ddrcReg_CTLR_T_FAW_PERIOD_SHIFT) + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* ARM PL341 AXI ID QOS configuration registers, offset 0x100 */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + +#define ddrcReg_CTLR_QOS_CNT 16 +#define ddrcReg_CTLR_QOS_MAX (ddrcReg_CTLR_QOS_CNT - 1) + + typedef struct { + uint32_t cfg[ddrcReg_CTLR_QOS_CNT]; + } ddrcReg_CTLR_QOS_REG_t; + +#define ddrcReg_CTLR_QOS_REG_OFFSET 0x100 +#define ddrcReg_CTLR_QOS_REGP ((volatile ddrcReg_CTLR_QOS_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_CTLR_QOS_REG_OFFSET)) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_QOS_CFG_MAX_SHIFT 2 +#define ddrcReg_CTLR_QOS_CFG_MAX_MASK (0xff << ddrcReg_CTLR_QOS_CFG_MAX_SHIFT) + +#define ddrcReg_CTLR_QOS_CFG_MIN_SHIFT 1 +#define ddrcReg_CTLR_QOS_CFG_MIN_MASK (1 << ddrcReg_CTLR_QOS_CFG_MIN_SHIFT) + +#define ddrcReg_CTLR_QOS_CFG_ENABLE (1 << 0) + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* ARM PL341 Memory chip configuration registers, offset 0x200 */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + +#define ddrcReg_CTLR_CHIP_CNT 4 +#define ddrcReg_CTLR_CHIP_MAX (ddrcReg_CTLR_CHIP_CNT - 1) + + typedef struct { + uint32_t cfg[ddrcReg_CTLR_CHIP_CNT]; + } ddrcReg_CTLR_CHIP_REG_t; + +#define ddrcReg_CTLR_CHIP_REG_OFFSET 0x200 +#define ddrcReg_CTLR_CHIP_REGP ((volatile ddrcReg_CTLR_CHIP_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_CTLR_CHIP_REG_OFFSET)) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_CHIP_CFG_MEM_ORG_MASK (1 << 16) +#define ddrcReg_CTLR_CHIP_CFG_MEM_ORG_ROW_BANK_COL (0 << 16) +#define ddrcReg_CTLR_CHIP_CFG_MEM_ORG_BANK_ROW_COL (1 << 16) + +#define ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MATCH_SHIFT 8 +#define ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MATCH_MASK (0xff << ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MATCH_SHIFT) + +#define ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MASK_SHIFT 0 +#define ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MASK_MASK (0xff << ddrcReg_CTLR_CHIP_CFG_AXI_ADDR_MASK_SHIFT) + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* ARM PL341 User configuration registers, offset 0x300 */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + +#define ddrcReg_CTLR_USER_OUTPUT_CNT 2 + + typedef struct { + uint32_t input; + uint32_t output[ddrcReg_CTLR_USER_OUTPUT_CNT]; + uint32_t feature; + } ddrcReg_CTLR_USER_REG_t; + +#define ddrcReg_CTLR_USER_REG_OFFSET 0x300 +#define ddrcReg_CTLR_USER_REGP ((volatile ddrcReg_CTLR_USER_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_CTLR_USER_REG_OFFSET)) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_USER_INPUT_STATUS_SHIFT 0 +#define ddrcReg_CTLR_USER_INPUT_STATUS_MASK (0xff << ddrcReg_CTLR_USER_INPUT_STATUS_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_USER_OUTPUT_CFG_SHIFT 0 +#define ddrcReg_CTLR_USER_OUTPUT_CFG_MASK (0xff << ddrcReg_CTLR_USER_OUTPUT_CFG_SHIFT) + +#define ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_SHIFT 1 +#define ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_MASK (1 << ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_BP134 (0 << ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_PL301 (1 << ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_REGISTERED ddrcReg_CTLR_USER_OUTPUT_0_CFG_SYNC_BRIDGE_PL301 + +/* ----------------------------------------------------- */ + +#define ddrcReg_CTLR_FEATURE_WRITE_BLOCK_DISABLE (1 << 2) +#define ddrcReg_CTLR_FEATURE_EARLY_BURST_RSP_DISABLE (1 << 0) + +/*********************************************************************/ +/* Broadcom DDR23 PHY register definitions */ +/*********************************************************************/ + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* Broadcom DDR23 PHY Address and Control register definitions */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + + typedef struct { + uint32_t revision; + uint32_t pmCtl; + REG32_RSVD(0x0008, 0x0010); + uint32_t pllStatus; + uint32_t pllCfg; + uint32_t pllPreDiv; + uint32_t pllDiv; + uint32_t pllCtl1; + uint32_t pllCtl2; + uint32_t ssCtl; + uint32_t ssCfg; + uint32_t vdlStatic; + uint32_t vdlDynamic; + uint32_t padIdle; + uint32_t pvtComp; + uint32_t padDrive; + uint32_t clkRgltrCtl; + } ddrcReg_PHY_ADDR_CTL_REG_t; + +#define ddrcReg_PHY_ADDR_CTL_REG_OFFSET 0x0400 +#define ddrcReg_PHY_ADDR_CTL_REGP ((volatile ddrcReg_PHY_ADDR_CTL_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_PHY_ADDR_CTL_REG_OFFSET)) + +/* @todo These SS definitions are duplicates of ones below */ + +#define ddrcReg_PHY_ADDR_SS_CTRL_ENABLE 0x00000001 +#define ddrcReg_PHY_ADDR_SS_CFG_CYCLE_PER_TICK_MASK 0xFFFF0000 +#define ddrcReg_PHY_ADDR_SS_CFG_CYCLE_PER_TICK_SHIFT 16 +#define ddrcReg_PHY_ADDR_SS_CFG_MIN_CYCLE_PER_TICK 10 /* Higher the value, lower the SS modulation frequency */ +#define ddrcReg_PHY_ADDR_SS_CFG_NDIV_AMPLITUDE_MASK 0x0000FFFF +#define ddrcReg_PHY_ADDR_SS_CFG_NDIV_AMPLITUDE_SHIFT 0 + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_REVISION_MAJOR_SHIFT 8 +#define ddrcReg_PHY_ADDR_CTL_REVISION_MAJOR_MASK (0xff << ddrcReg_PHY_ADDR_CTL_REVISION_MAJOR_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_REVISION_MINOR_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_REVISION_MINOR_MASK (0xff << ddrcReg_PHY_ADDR_CTL_REVISION_MINOR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_CLK_PM_CTL_DDR_CLK_DISABLE (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_STATUS_LOCKED (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_DIV2_CLK_RESET (1 << 31) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_TEST_SEL_SHIFT 17 +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_TEST_SEL_MASK (0x1f << ddrcReg_PHY_ADDR_CTL_PLL_CFG_TEST_SEL_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_TEST_ENABLE (1 << 16) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_BGAP_ADJ_SHIFT 12 +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_BGAP_ADJ_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PLL_CFG_BGAP_ADJ_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_VCO_RNG (1 << 7) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_CH1_PWRDWN (1 << 6) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_BYPASS_ENABLE (1 << 5) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_CLKOUT_ENABLE (1 << 4) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_D_RESET (1 << 3) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_A_RESET (1 << 2) +#define ddrcReg_PHY_ADDR_CTL_PLL_CFG_PWRDWN (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_DITHER_MFB (1 << 26) +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_PWRDWN (1 << 25) + +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_MODE_SHIFT 20 +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_MODE_MASK (0x7 << ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_MODE_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_INT_SHIFT 8 +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_INT_MASK (0x1ff << ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_INT_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P2_SHIFT 4 +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P2_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P2_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P1_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P1_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PLL_PRE_DIV_P1_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_DIV_M1_SHIFT 24 +#define ddrcReg_PHY_ADDR_CTL_PLL_DIV_M1_MASK (0xff << ddrcReg_PHY_ADDR_CTL_PLL_DIV_M1_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_DIV_FRAC_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_PLL_DIV_FRAC_MASK (0xffffff << ddrcReg_PHY_ADDR_CTL_PLL_DIV_FRAC_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_TESTA_SHIFT 30 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_TESTA_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_TESTA_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XS_SHIFT 27 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XS_MASK (0x7 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XS_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XF_SHIFT 24 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XF_MASK (0x7 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_KVCO_XF_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_LPF_BW_SHIFT 22 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_LPF_BW_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_LPF_BW_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_LF_ORDER (0x1 << 21) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CN_SHIFT 19 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CN_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CN_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RN_SHIFT 17 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RN_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RN_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CP_SHIFT 15 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CP_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CP_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CZ_SHIFT 13 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CZ_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_CZ_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RZ_SHIFT 10 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RZ_MASK (0x7 << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_RZ_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICPX_SHIFT 5 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICPX_MASK (0x1f << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICPX_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICP_OFF_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICP_OFF_MASK (0x1f << ddrcReg_PHY_ADDR_CTL_PLL_CTL1_ICP_OFF_SHIFT) + +/* ----------------------------------------------------- */ +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_PTAP_ADJ_SHIFT 4 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_PTAP_ADJ_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL2_PTAP_ADJ_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_CTAP_ADJ_SHIFT 2 +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_CTAP_ADJ_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_PLL_CTL2_CTAP_ADJ_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_LOWCUR_ENABLE (0x1 << 1) +#define ddrcReg_PHY_ADDR_CTL_PLL_CTL2_BIASIN_ENABLE (0x1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_SS_EN_ENABLE (0x1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_CYC_PER_TICK_SHIFT 16 +#define ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_CYC_PER_TICK_MASK (0xffff << ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_CYC_PER_TICK_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_NDIV_AMP_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_NDIV_AMP_MASK (0xffff << ddrcReg_PHY_ADDR_CTL_PLL_SS_CFG_NDIV_AMP_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_FORCE (1 << 20) +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_ENABLE (1 << 16) + +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_FALL_SHIFT 12 +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_FALL_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_FALL_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_RISE_SHIFT 8 +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_RISE_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_RISE_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_STEP_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_STEP_MASK (0x3f << ddrcReg_PHY_ADDR_CTL_VDL_STATIC_OVR_STEP_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_ENABLE (1 << 16) + +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_FALL_SHIFT 12 +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_FALL_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_FALL_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_RISE_SHIFT 8 +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_RISE_MASK (0x3 << ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_RISE_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_STEP_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_STEP_MASK (0x3f << ddrcReg_PHY_ADDR_CTL_VDL_DYNAMIC_OVR_STEP_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_ENABLE (1u << 31) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_RXENB_DISABLE (1 << 8) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CTL_IDDQ_DISABLE (1 << 6) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CTL_REB_DISABLE (1 << 5) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CTL_OEB_DISABLE (1 << 4) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CKE_IDDQ_DISABLE (1 << 2) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CKE_REB_DISABLE (1 << 1) +#define ddrcReg_PHY_ADDR_CTL_PAD_IDLE_CKE_OEB_DISABLE (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_PD_DONE (1 << 30) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ND_DONE (1 << 29) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_SAMPLE_DONE (1 << 28) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_SAMPLE_AUTO_ENABLE (1 << 27) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_SAMPLE_ENABLE (1 << 26) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_OVR_ENABLE (1 << 25) +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_OVR_ENABLE (1 << 24) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_PD_SHIFT 20 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_PD_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_PD_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ND_SHIFT 16 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ND_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_ND_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_PD_SHIFT 12 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_PD_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_PD_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_ND_SHIFT 8 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_ND_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_ADDR_ND_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_PD_SHIFT 4 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_PD_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_PD_SHIFT) + +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_ND_SHIFT 0 +#define ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_ND_MASK (0xf << ddrcReg_PHY_ADDR_CTL_PVT_COMP_DQ_ND_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_PAD_DRIVE_RT60B (1 << 4) +#define ddrcReg_PHY_ADDR_CTL_PAD_DRIVE_SEL_SSTL18 (1 << 3) +#define ddrcReg_PHY_ADDR_CTL_PAD_DRIVE_SELTXDRV_CI (1 << 2) +#define ddrcReg_PHY_ADDR_CTL_PAD_DRIVE_SELRXDRV (1 << 1) +#define ddrcReg_PHY_ADDR_CTL_PAD_DRIVE_SLEW (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_ADDR_CTL_CLK_RGLTR_CTL_PWR_HALF (1 << 1) +#define ddrcReg_PHY_ADDR_CTL_CLK_RGLTR_CTL_PWR_OFF (1 << 0) + +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/* Broadcom DDR23 PHY Byte Lane register definitions */ +/* -------------------------------------------------------------------- */ +/* -------------------------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_CNT 2 +#define ddrcReg_PHY_BYTE_LANE_MAX (ddrcReg_CTLR_BYTE_LANE_CNT - 1) + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_CNT 8 + + typedef struct { + uint32_t revision; + uint32_t vdlCalibrate; + uint32_t vdlStatus; + REG32_RSVD(0x000c, 0x0010); + uint32_t vdlOverride[ddrcReg_PHY_BYTE_LANE_VDL_OVR_CNT]; + uint32_t readCtl; + uint32_t readStatus; + uint32_t readClear; + uint32_t padIdleCtl; + uint32_t padDriveCtl; + uint32_t padClkCtl; + uint32_t writeCtl; + uint32_t clkRegCtl; + } ddrcReg_PHY_BYTE_LANE_REG_t; + +/* There are 2 instances of the byte Lane registers, one for each byte lane. */ +#define ddrcReg_PHY_BYTE_LANE_1_REG_OFFSET 0x0500 +#define ddrcReg_PHY_BYTE_LANE_2_REG_OFFSET 0x0600 + +#define ddrcReg_PHY_BYTE_LANE_1_REGP ((volatile ddrcReg_PHY_BYTE_LANE_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_PHY_BYTE_LANE_1_REG_OFFSET)) +#define ddrcReg_PHY_BYTE_LANE_2_REGP ((volatile ddrcReg_PHY_BYTE_LANE_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_PHY_BYTE_LANE_2_REG_OFFSET)) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_REVISION_MAJOR_SHIFT 8 +#define ddrcReg_PHY_BYTE_LANE_REVISION_MAJOR_MASK (0xff << ddrcReg_PHY_BYTE_LANE_REVISION_MAJOR_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_REVISION_MINOR_SHIFT 0 +#define ddrcReg_PHY_BYTE_LANE_REVISION_MINOR_MASK (0xff << ddrcReg_PHY_BYTE_LANE_REVISION_MINOR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_CLK_2CYCLE (1 << 4) +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_CLK_1CYCLE (0 << 4) + +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_TEST (1 << 3) +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_ALWAYS (1 << 2) +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_ONCE (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_VDL_CALIB_FAST (1 << 0) + +/* ----------------------------------------------------- */ + +/* The byte lane VDL status calibTotal[9:0] is comprised of [9:4] step value, [3:2] fine fall */ +/* and [1:0] fine rise. Note that calibTotal[9:0] is located at bit 4 in the VDL status */ +/* register. The fine rise and fall are no longer used, so add some definitions for just */ +/* the step setting to simplify things. */ + +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_STEP_SHIFT 8 +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_STEP_MASK (0x3f << ddrcReg_PHY_BYTE_LANE_VDL_STATUS_STEP_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_TOTAL_SHIFT 4 +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_TOTAL_MASK (0x3ff << ddrcReg_PHY_BYTE_LANE_VDL_STATUS_TOTAL_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_LOCK (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_VDL_STATUS_IDLE (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_ENABLE (1 << 16) + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_FALL_SHIFT 12 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_FALL_MASK (0x3 << ddrcReg_PHY_BYTE_LANE_VDL_OVR_FALL_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_RISE_SHIFT 8 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_RISE_MASK (0x3 << ddrcReg_PHY_BYTE_LANE_VDL_OVR_RISE_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_STEP_SHIFT 0 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_STEP_MASK (0x3f << ddrcReg_PHY_BYTE_LANE_VDL_OVR_STEP_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_STATIC_READ_DQS_P 0 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_STATIC_READ_DQS_N 1 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_STATIC_READ_EN 2 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_STATIC_WRITE_DQ_DQM 3 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_DYNAMIC_READ_DQS_P 4 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_DYNAMIC_READ_DQS_N 5 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_DYNAMIC_READ_EN 6 +#define ddrcReg_PHY_BYTE_LANE_VDL_OVR_IDX_DYNAMIC_WRITE_DQ_DQM 7 + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_DELAY_SHIFT 8 +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_DELAY_MASK (0x3 << ddrcReg_PHY_BYTE_LANE_READ_CTL_DELAY_SHIFT) + +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_DQ_ODT_ENABLE (1 << 3) +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_DQ_ODT_ADJUST (1 << 2) +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_RD_ODT_ENABLE (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_READ_CTL_RD_ODT_ADJUST (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_READ_STATUS_ERROR_SHIFT 0 +#define ddrcReg_PHY_BYTE_LANE_READ_STATUS_ERROR_MASK (0xf << ddrcReg_PHY_BYTE_LANE_READ_STATUS_ERROR_SHIFT) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_READ_CLEAR_STATUS (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_ENABLE (1u << 31) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DM_RXENB_DISABLE (1 << 19) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DM_IDDQ_DISABLE (1 << 18) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DM_REB_DISABLE (1 << 17) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DM_OEB_DISABLE (1 << 16) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQ_RXENB_DISABLE (1 << 15) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQ_IDDQ_DISABLE (1 << 14) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQ_REB_DISABLE (1 << 13) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQ_OEB_DISABLE (1 << 12) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_READ_ENB_RXENB_DISABLE (1 << 11) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_READ_ENB_IDDQ_DISABLE (1 << 10) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_READ_ENB_REB_DISABLE (1 << 9) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_READ_ENB_OEB_DISABLE (1 << 8) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQS_RXENB_DISABLE (1 << 7) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQS_IDDQ_DISABLE (1 << 6) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQS_REB_DISABLE (1 << 5) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_DQS_OEB_DISABLE (1 << 4) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_CLK_RXENB_DISABLE (1 << 3) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_CLK_IDDQ_DISABLE (1 << 2) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_CLK_REB_DISABLE (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_PAD_IDLE_CTL_CLK_OEB_DISABLE (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_RT60B_DDR_READ_ENB (1 << 5) +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_RT60B (1 << 4) +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_SEL_SSTL18 (1 << 3) +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_SELTXDRV_CI (1 << 2) +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_SELRXDRV (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_PAD_DRIVE_CTL_SLEW (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_PAD_CLK_CTL_DISABLE (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_WRITE_CTL_PREAMBLE_DDR3 (1 << 0) + +/* ----------------------------------------------------- */ + +#define ddrcReg_PHY_BYTE_LANE_CLK_REG_CTL_PWR_HALF (1 << 1) +#define ddrcReg_PHY_BYTE_LANE_CLK_REG_CTL_PWR_OFF (1 << 0) + +/*********************************************************************/ +/* ARM PL341 DDRC to Broadcom DDR23 PHY glue register definitions */ +/*********************************************************************/ + + typedef struct { + uint32_t cfg; + uint32_t actMonCnt; + uint32_t ctl; + uint32_t lbistCtl; + uint32_t lbistSeed; + uint32_t lbistStatus; + uint32_t tieOff; + uint32_t actMonClear; + uint32_t status; + uint32_t user; + } ddrcReg_CTLR_PHY_GLUE_REG_t; + +#define ddrcReg_CTLR_PHY_GLUE_OFFSET 0x0700 +#define ddrcReg_CTLR_PHY_GLUE_REGP ((volatile ddrcReg_CTLR_PHY_GLUE_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_CTLR_PHY_GLUE_OFFSET)) + +/* ----------------------------------------------------- */ + +/* DDR2 / AXI block phase alignment interrupt control */ +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT 18 +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_MASK (0x3 << ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_OFF (0 << ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_ON_TIGHT (1 << ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_ON_MEDIUM (2 << ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_INT_ON_LOOSE (3 << ddrcReg_CTLR_PHY_GLUE_CFG_INT_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_SHIFT 17 +#define ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_MASK (1 << ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_DIFFERENTIAL (0 << ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_CMOS (1 << ddrcReg_CTLR_PHY_GLUE_CFG_PLL_REFCLK_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHIFT 16 +#define ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_MASK (1 << ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_DEEP (0 << ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHALLOW (1 << ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_HW_FIXED_ALIGNMENT_DISABLED ddrcReg_CTLR_PHY_GLUE_CFG_DIV2CLK_TREE_SHALLOW + +#define ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_SHIFT 15 +#define ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_MASK (1 << ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_BP134 (0 << ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_PL301 (1 << ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_REGISTERED ddrcReg_CTLR_PHY_GLUE_CFG_SYNC_BRIDGE_PL301 + +/* Software control of PHY VDL updates from control register settings. Bit 13 enables the use of Bit 14. */ +/* If software control is not enabled, then updates occur when a refresh command is issued by the hardware */ +/* controller. If 2 chips selects are being used, then software control must be enabled. */ +#define ddrcReg_CTLR_PHY_GLUE_CFG_PHY_VDL_UPDATE_SW_CTL_LOAD (1 << 14) +#define ddrcReg_CTLR_PHY_GLUE_CFG_PHY_VDL_UPDATE_SW_CTL_ENABLE (1 << 13) + +/* Use these to bypass a pipeline stage. By default the ADDR is off but the BYTE LANE in / out are on. */ +#define ddrcReg_CTLR_PHY_GLUE_CFG_PHY_ADDR_CTL_IN_BYPASS_PIPELINE_STAGE (1 << 12) +#define ddrcReg_CTLR_PHY_GLUE_CFG_PHY_BYTE_LANE_IN_BYPASS_PIPELINE_STAGE (1 << 11) +#define ddrcReg_CTLR_PHY_GLUE_CFG_PHY_BYTE_LANE_OUT_BYPASS_PIPELINE_STAGE (1 << 10) + +/* Chip select count */ +#define ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_SHIFT 9 +#define ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_MASK (1 << ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_1 (0 << ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_2 (1 << ddrcReg_CTLR_PHY_GLUE_CFG_CS_CNT_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_CLK_SHIFT 8 +#define ddrcReg_CTLR_PHY_GLUE_CFG_CLK_ASYNC (0 << ddrcReg_CTLR_PHY_GLUE_CFG_CLK_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_CLK_SYNC (1 << ddrcReg_CTLR_PHY_GLUE_CFG_CLK_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_CKE_INIT_SHIFT 7 +#define ddrcReg_CTLR_PHY_GLUE_CFG_CKE_INIT_LOW (0 << ddrcReg_CTLR_PHY_GLUE_CFG_CKE_INIT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_CKE_INIT_HIGH (1 << ddrcReg_CTLR_PHY_GLUE_CFG_CKE_INIT_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_DQM_INIT_SHIFT 6 +#define ddrcReg_CTLR_PHY_GLUE_CFG_DQM_INIT_LOW (0 << ddrcReg_CTLR_PHY_GLUE_CFG_DQM_INIT_SHIFT) +#define ddrcReg_CTLR_PHY_GLUE_CFG_DQM_INIT_HIGH (1 << ddrcReg_CTLR_PHY_GLUE_CFG_DQM_INIT_SHIFT) + +#define ddrcReg_CTLR_PHY_GLUE_CFG_CAS_LATENCY_SHIFT 0 +#define ddrcReg_CTLR_PHY_GLUE_CFG_CAS_LATENCY_MASK (0x7 << ddrcReg_CTLR_PHY_GLUE_CFG_CAS_LATENCY_SHIFT) + +/* ----------------------------------------------------- */ +#define ddrcReg_CTLR_PHY_GLUE_STATUS_PHASE_SHIFT 0 +#define ddrcReg_CTLR_PHY_GLUE_STATUS_PHASE_MASK (0x7f << ddrcReg_CTLR_PHY_GLUE_STATUS_PHASE_SHIFT) + +/* ---- Public Function Prototypes --------------------------------------- */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* DDRC_REG_H */ -- GitLab From f1947c7a6717e437d9fe0e27a76bacf77f570d2d Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:04:54 +0100 Subject: [PATCH 0983/1002] ARM: 5654/1: bcmring: add csp chipc hardware register file add csp chipc hardware register file Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../include/mach/csp/chipcHw_reg.h | 530 ++++++++++++++++++ 1 file changed, 530 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h new file mode 100644 index 0000000000000..b162448f613c9 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h @@ -0,0 +1,530 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file chipcHw_reg.h +* +* @brief Definitions for low level chip control registers +* +*/ +/****************************************************************************/ +#ifndef CHIPCHW_REG_H +#define CHIPCHW_REG_H + +#include <mach/csp/mm_io.h> +#include <csp/reg.h> +#include <mach/csp/ddrcReg.h> + +#define chipcHw_BASE_ADDRESS MM_IO_BASE_CHIPC + +typedef struct { + uint32_t ChipId; /* Chip ID */ + uint32_t DDRClock; /* PLL1 Channel 1 for DDR clock */ + uint32_t ARMClock; /* PLL1 Channel 2 for ARM clock */ + uint32_t ESWClock; /* PLL1 Channel 3 for ESW system clock */ + uint32_t VPMClock; /* PLL1 Channel 4 for VPM clock */ + uint32_t ESW125Clock; /* PLL1 Channel 5 for ESW 125MHz clock */ + uint32_t UARTClock; /* PLL1 Channel 6 for UART clock */ + uint32_t SDIO0Clock; /* PLL1 Channel 7 for SDIO 0 clock */ + uint32_t SDIO1Clock; /* PLL1 Channel 8 for SDIO 1 clock */ + uint32_t SPIClock; /* PLL1 Channel 9 for SPI master Clock */ + uint32_t ETMClock; /* PLL1 Channel 10 for ARM ETM Clock */ + + uint32_t ACLKClock; /* ACLK Clock (Divider) */ + uint32_t OTPClock; /* OTP Clock (Divider) */ + uint32_t I2CClock; /* I2C Clock (CK_13m) (Divider) */ + uint32_t I2S0Clock; /* I2S0 Clock (Divider) */ + uint32_t RTBUSClock; /* RTBUS (DDR PHY Config.) Clock (Divider) */ + uint32_t pad1; + uint32_t APM100Clock; /* APM 100MHz CLK Clock (Divider) */ + uint32_t TSCClock; /* TSC Clock (Divider) */ + uint32_t LEDClock; /* LED Clock (Divider) */ + + uint32_t USBClock; /* PLL2 Channel 1 for USB clock */ + uint32_t LCDClock; /* PLL2 Channel 2 for LCD clock */ + uint32_t APMClock; /* PLL2 Channel 3 for APM 200 MHz clock */ + + uint32_t BusIntfClock; /* Bus interface clock */ + + uint32_t PLLStatus; /* PLL status register (PLL1) */ + uint32_t PLLConfig; /* PLL configuration register (PLL1) */ + uint32_t PLLPreDivider; /* PLL pre-divider control register (PLL1) */ + uint32_t PLLDivider; /* PLL divider control register (PLL1) */ + uint32_t PLLControl1; /* PLL analog control register #1 (PLL1) */ + uint32_t PLLControl2; /* PLL analog control register #2 (PLL1) */ + + uint32_t I2S1Clock; /* I2S1 Clock */ + uint32_t AudioEnable; /* Enable/ disable audio channel */ + uint32_t SoftReset1; /* Reset blocks */ + uint32_t SoftReset2; /* Reset blocks */ + uint32_t Spare1; /* Phase align interrupts */ + uint32_t Sticky; /* Sticky bits */ + uint32_t MiscCtrl; /* Misc. control */ + uint32_t pad3[3]; + + uint32_t PLLStatus2; /* PLL status register (PLL2) */ + uint32_t PLLConfig2; /* PLL configuration register (PLL2) */ + uint32_t PLLPreDivider2; /* PLL pre-divider control register (PLL2) */ + uint32_t PLLDivider2; /* PLL divider control register (PLL2) */ + uint32_t PLLControl12; /* PLL analog control register #1 (PLL2) */ + uint32_t PLLControl22; /* PLL analog control register #2 (PLL2) */ + + uint32_t DDRPhaseCtrl1; /* DDR Clock Phase Alignment control1 */ + uint32_t VPMPhaseCtrl1; /* VPM Clock Phase Alignment control1 */ + uint32_t PhaseAlignStatus; /* DDR/VPM Clock Phase Alignment Status */ + uint32_t PhaseCtrlStatus; /* DDR/VPM Clock HW DDR/VPM ph_ctrl and load_ch Status */ + uint32_t DDRPhaseCtrl2; /* DDR Clock Phase Alignment control2 */ + uint32_t VPMPhaseCtrl2; /* VPM Clock Phase Alignment control2 */ + uint32_t pad4[9]; + + uint32_t SoftOTP1; /* Software OTP control */ + uint32_t SoftOTP2; /* Software OTP control */ + uint32_t SoftStraps; /* Software strap */ + uint32_t PinStraps; /* Pin Straps */ + uint32_t DiffOscCtrl; /* Diff oscillator control */ + uint32_t DiagsCtrl; /* Diagnostic control */ + uint32_t DiagsOutputCtrl; /* Diagnostic output enable */ + uint32_t DiagsReadBackCtrl; /* Diagnostic read back control */ + + uint32_t LcdPifMode; /* LCD/PIF Pin Sharing MUX Mode */ + + uint32_t GpioMux_0_7; /* Pin Sharing MUX0 Control */ + uint32_t GpioMux_8_15; /* Pin Sharing MUX1 Control */ + uint32_t GpioMux_16_23; /* Pin Sharing MUX2 Control */ + uint32_t GpioMux_24_31; /* Pin Sharing MUX3 Control */ + uint32_t GpioMux_32_39; /* Pin Sharing MUX4 Control */ + uint32_t GpioMux_40_47; /* Pin Sharing MUX5 Control */ + uint32_t GpioMux_48_55; /* Pin Sharing MUX6 Control */ + uint32_t GpioMux_56_63; /* Pin Sharing MUX7 Control */ + + uint32_t GpioSR_0_7; /* Slew rate for GPIO 0 - 7 */ + uint32_t GpioSR_8_15; /* Slew rate for GPIO 8 - 15 */ + uint32_t GpioSR_16_23; /* Slew rate for GPIO 16 - 23 */ + uint32_t GpioSR_24_31; /* Slew rate for GPIO 24 - 31 */ + uint32_t GpioSR_32_39; /* Slew rate for GPIO 32 - 39 */ + uint32_t GpioSR_40_47; /* Slew rate for GPIO 40 - 47 */ + uint32_t GpioSR_48_55; /* Slew rate for GPIO 48 - 55 */ + uint32_t GpioSR_56_63; /* Slew rate for GPIO 56 - 63 */ + uint32_t MiscSR_0_7; /* Slew rate for MISC 0 - 7 */ + uint32_t MiscSR_8_15; /* Slew rate for MISC 8 - 15 */ + + uint32_t GpioPull_0_15; /* Pull up registers for GPIO 0 - 15 */ + uint32_t GpioPull_16_31; /* Pull up registers for GPIO 16 - 31 */ + uint32_t GpioPull_32_47; /* Pull up registers for GPIO 32 - 47 */ + uint32_t GpioPull_48_63; /* Pull up registers for GPIO 48 - 63 */ + uint32_t MiscPull_0_15; /* Pull up registers for MISC 0 - 15 */ + + uint32_t GpioInput_0_31; /* Input type for GPIO 0 - 31 */ + uint32_t GpioInput_32_63; /* Input type for GPIO 32 - 63 */ + uint32_t MiscInput_0_15; /* Input type for MISC 0 - 16 */ +} chipcHw_REG_t; + +#define pChipcHw ((volatile chipcHw_REG_t *) chipcHw_BASE_ADDRESS) +#define pChipcPhysical ((volatile chipcHw_REG_t *) MM_ADDR_IO_CHIPC) + +#define chipcHw_REG_CHIPID_BASE_MASK 0xFFFFF000 +#define chipcHw_REG_CHIPID_BASE_SHIFT 12 +#define chipcHw_REG_CHIPID_REV_MASK 0x00000FFF +#define chipcHw_REG_REV_A0 0xA00 +#define chipcHw_REG_REV_B0 0x0B0 + +#define chipcHw_REG_PLL_STATUS_CONTROL_ENABLE 0x80000000 /* Allow controlling PLL registers */ +#define chipcHw_REG_PLL_STATUS_LOCKED 0x00000001 /* PLL is settled */ +#define chipcHw_REG_PLL_CONFIG_D_RESET 0x00000008 /* Digital reset */ +#define chipcHw_REG_PLL_CONFIG_A_RESET 0x00000004 /* Analog reset */ +#define chipcHw_REG_PLL_CONFIG_BYPASS_ENABLE 0x00000020 /* Bypass enable */ +#define chipcHw_REG_PLL_CONFIG_OUTPUT_ENABLE 0x00000010 /* Output enable */ +#define chipcHw_REG_PLL_CONFIG_POWER_DOWN 0x00000001 /* Power down */ +#define chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ 1600000000 /* 1.6GHz VCO split frequency */ +#define chipcHw_REG_PLL_CONFIG_VCO_800_1600 0x00000000 /* VCO range 800-1600 MHz */ +#define chipcHw_REG_PLL_CONFIG_VCO_1601_3200 0x00000080 /* VCO range 1601-3200 MHz */ +#define chipcHw_REG_PLL_CONFIG_TEST_ENABLE 0x00010000 /* PLL test output enable */ +#define chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK 0x003E0000 /* Mask to set test values */ +#define chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT 17 + +#define chipcHw_REG_PLL_CLOCK_PHASE_COMP 0x00800000 /* Phase comparator output */ +#define chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK 0x00300000 /* Clock to bus ratio mask */ +#define chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT 20 /* Number of bits to be shifted */ +#define chipcHw_REG_PLL_CLOCK_POWER_DOWN 0x00080000 /* PLL channel power down */ +#define chipcHw_REG_PLL_CLOCK_SOURCE_GPIO 0x00040000 /* Use GPIO as source */ +#define chipcHw_REG_PLL_CLOCK_BYPASS_SELECT 0x00020000 /* Select bypass clock */ +#define chipcHw_REG_PLL_CLOCK_OUTPUT_ENABLE 0x00010000 /* Clock gated ON */ +#define chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE 0x00008000 /* Clock phase update enable */ +#define chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT 8 /* Number of bits to be shifted */ +#define chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK 0x00003F00 /* Phase control mask */ +#define chipcHw_REG_PLL_CLOCK_MDIV_MASK 0x000000FF /* Clock post divider mask + + 00000000 = divide-by-256 + 00000001 = divide-by-1 + 00000010 = divide-by-2 + 00000011 = divide-by-3 + 00000100 = divide-by-4 + 00000101 = divide-by-5 + 00000110 = divide-by-6 + . + . + 11111011 = divide-by-251 + 11111100 = divide-by-252 + 11111101 = divide-by-253 + 11111110 = divide-by-254 + */ + +#define chipcHw_REG_DIV_CLOCK_SOURCE_OTHER 0x00040000 /* NON-PLL clock source select */ +#define chipcHw_REG_DIV_CLOCK_BYPASS_SELECT 0x00020000 /* NON-PLL clock bypass enable */ +#define chipcHw_REG_DIV_CLOCK_OUTPUT_ENABLE 0x00010000 /* NON-PLL clock output enable */ +#define chipcHw_REG_DIV_CLOCK_DIV_MASK 0x000000FF /* NON-PLL clock post-divide mask */ +#define chipcHw_REG_DIV_CLOCK_DIV_256 0x00000000 /* NON-PLL clock post-divide by 256 */ + +#define chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT 0 +#define chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT 4 +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT 8 +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK 0x0001FF00 +#define chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN 0x02000000 +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK 0x00700000 /* Divider mask */ +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER 0x00000000 /* Integer-N Mode */ +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_UNIT 0x00100000 /* MASH Sigma-Delta Modulator Unit Mode */ +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MFB_UNIT 0x00200000 /* MFB Sigma-Delta Modulator Unit Mode */ +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_1_8 0x00300000 /* MASH Sigma-Delta Modulator 1/8 Mode */ +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MFB_1_8 0x00400000 /* MFB Sigma-Delta Modulator 1/8 Mode */ + +#define chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vco) ((vco) / chipcHw_XTAL_FREQ_Hz) +#define chipcHw_REG_PLL_PREDIVIDER_P1 1 +#define chipcHw_REG_PLL_PREDIVIDER_P2 1 + +#define chipcHw_REG_PLL_DIVIDER_M1DIV 0x03000000 +#define chipcHw_REG_PLL_DIVIDER_FRAC 0x00FFFFFF /* Fractional divider */ + +#define chipcHw_REG_PLL_DIVIDER_NDIV_f_SS (0x00FFFFFF) /* To attain spread with max frequency */ + +#define chipcHw_REG_PLL_DIVIDER_NDIV_f 0 /* ndiv_frac = chipcHw_REG_PLL_DIVIDER_NDIV_f / + chipcHw_REG_PLL_DIVIDER_FRAC + = 0, when SS is disable + */ + +#define chipcHw_REG_PLL_DIVIDER_MDIV(vco, Hz) ((chipcHw_divide((vco), (Hz)) > 255) ? 0 : chipcHw_divide((vco), (Hz))) + +#define chipcHw_REG_ACLKClock_CLK_DIV_MASK 0x3 + +/* System booting strap options */ +#define chipcHw_STRAPS_SOFT_OVERRIDE 0x00000001 /* Software Strap Override */ + +#define chipcHw_STRAPS_BOOT_DEVICE_NAND_FLASH_8 0x00000000 /* 8 bit NAND FLASH Boot */ +#define chipcHw_STRAPS_BOOT_DEVICE_NOR_FLASH_16 0x00000002 /* 16 bit NOR FLASH Boot */ +#define chipcHw_STRAPS_BOOT_DEVICE_SERIAL_FLASH 0x00000004 /* Serial FLASH Boot */ +#define chipcHw_STRAPS_BOOT_DEVICE_NAND_FLASH_16 0x00000006 /* 16 bit NAND FLASH Boot */ +#define chipcHw_STRAPS_BOOT_DEVICE_UART 0x00000008 /* UART Boot */ +#define chipcHw_STRAPS_BOOT_DEVICE_MASK 0x0000000E /* Mask */ + +/* System boot option */ +#define chipcHw_STRAPS_BOOT_OPTION_BROM 0x00000000 /* Boot from Boot ROM */ +#define chipcHw_STRAPS_BOOT_OPTION_ARAM 0x00000020 /* Boot from ARAM */ +#define chipcHw_STRAPS_BOOT_OPTION_NOR 0x00000030 /* Boot from NOR flash */ + +/* NAND Flash page size strap options */ +#define chipcHw_STRAPS_NAND_PAGESIZE_512 0x00000000 /* NAND FLASH page size of 512 bytes */ +#define chipcHw_STRAPS_NAND_PAGESIZE_2048 0x00000040 /* NAND FLASH page size of 2048 bytes */ +#define chipcHw_STRAPS_NAND_PAGESIZE_4096 0x00000080 /* NAND FLASH page size of 4096 bytes */ +#define chipcHw_STRAPS_NAND_PAGESIZE_EXT 0x000000C0 /* NAND FLASH page of extened size */ +#define chipcHw_STRAPS_NAND_PAGESIZE_MASK 0x000000C0 /* Mask */ + +#define chipcHw_STRAPS_NAND_EXTRA_CYCLE 0x00000400 /* NAND FLASH address cycle configuration */ +#define chipcHw_STRAPS_REBOOT_TO_UART 0x00000800 /* Reboot to UART on error */ + +/* Secure boot mode strap options */ +#define chipcHw_STRAPS_BOOT_MODE_NORMAL 0x00000000 /* Normal Boot */ +#define chipcHw_STRAPS_BOOT_MODE_DBG_SW 0x00000100 /* Software debugging Boot */ +#define chipcHw_STRAPS_BOOT_MODE_DBG_BOOT 0x00000200 /* Boot rom debugging Boot */ +#define chipcHw_STRAPS_BOOT_MODE_NORMAL_QUIET 0x00000300 /* Normal Boot (Quiet BootRom) */ +#define chipcHw_STRAPS_BOOT_MODE_MASK 0x00000300 /* Mask */ + +/* Slave Mode straps */ +#define chipcHw_STRAPS_I2CS 0x02000000 /* I2C Slave */ +#define chipcHw_STRAPS_SPIS 0x01000000 /* SPI Slave */ + +/* Strap pin options */ +#define chipcHw_REG_SW_STRAPS ((pChipcHw->PinStraps & 0x0000FC00) >> 10) + +/* PIF/LCD pin sharing defines */ +#define chipcHw_REG_LCD_PIN_ENABLE 0x00000001 /* LCD Controller is used and the pins have LCD functions */ +#define chipcHw_REG_PIF_PIN_ENABLE 0x00000002 /* LCD pins are used to perform PIF functions */ + +#define chipcHw_GPIO_COUNT 61 /* Number of GPIO pin accessible thorugh CHIPC */ + +/* NOTE: Any changes to these constants will require a corresponding change to chipcHw_str.c */ +#define chipcHw_REG_GPIO_MUX_KEYPAD 0x00000001 /* GPIO mux for Keypad */ +#define chipcHw_REG_GPIO_MUX_I2CH 0x00000002 /* GPIO mux for I2CH */ +#define chipcHw_REG_GPIO_MUX_SPI 0x00000003 /* GPIO mux for SPI */ +#define chipcHw_REG_GPIO_MUX_UART 0x00000004 /* GPIO mux for UART */ +#define chipcHw_REG_GPIO_MUX_LEDMTXP 0x00000005 /* GPIO mux for LEDMTXP */ +#define chipcHw_REG_GPIO_MUX_LEDMTXS 0x00000006 /* GPIO mux for LEDMTXS */ +#define chipcHw_REG_GPIO_MUX_SDIO0 0x00000007 /* GPIO mux for SDIO0 */ +#define chipcHw_REG_GPIO_MUX_SDIO1 0x00000008 /* GPIO mux for SDIO1 */ +#define chipcHw_REG_GPIO_MUX_PCM 0x00000009 /* GPIO mux for PCM */ +#define chipcHw_REG_GPIO_MUX_I2S 0x0000000A /* GPIO mux for I2S */ +#define chipcHw_REG_GPIO_MUX_ETM 0x0000000B /* GPIO mux for ETM */ +#define chipcHw_REG_GPIO_MUX_DEBUG 0x0000000C /* GPIO mux for DEBUG */ +#define chipcHw_REG_GPIO_MUX_MISC 0x0000000D /* GPIO mux for MISC */ +#define chipcHw_REG_GPIO_MUX_GPIO 0x00000000 /* GPIO mux for GPIO */ +#define chipcHw_REG_GPIO_MUX(pin) (&pChipcHw->GpioMux_0_7 + ((pin) >> 3)) +#define chipcHw_REG_GPIO_MUX_POSITION(pin) (((pin) & 0x00000007) << 2) +#define chipcHw_REG_GPIO_MUX_MASK 0x0000000F /* Mask */ + +#define chipcHw_REG_SLEW_RATE_HIGH 0x00000000 /* High speed slew rate */ +#define chipcHw_REG_SLEW_RATE_NORMAL 0x00000008 /* Normal slew rate */ + /* Pins beyond 42 are defined by skipping 8 bits within the register */ +#define chipcHw_REG_SLEW_RATE(pin) (((pin) > 42) ? (&pChipcHw->GpioSR_0_7 + (((pin) + 2) >> 3)) : (&pChipcHw->GpioSR_0_7 + ((pin) >> 3))) +#define chipcHw_REG_SLEW_RATE_POSITION(pin) (((pin) > 42) ? ((((pin) + 2) & 0x00000007) << 2) : (((pin) & 0x00000007) << 2)) +#define chipcHw_REG_SLEW_RATE_MASK 0x00000008 /* Mask */ + +#define chipcHw_REG_CURRENT_STRENGTH_2mA 0x00000001 /* Current driving strength 2 milli ampere */ +#define chipcHw_REG_CURRENT_STRENGTH_4mA 0x00000002 /* Current driving strength 4 milli ampere */ +#define chipcHw_REG_CURRENT_STRENGTH_6mA 0x00000004 /* Current driving strength 6 milli ampere */ +#define chipcHw_REG_CURRENT_STRENGTH_8mA 0x00000005 /* Current driving strength 8 milli ampere */ +#define chipcHw_REG_CURRENT_STRENGTH_10mA 0x00000006 /* Current driving strength 10 milli ampere */ +#define chipcHw_REG_CURRENT_STRENGTH_12mA 0x00000007 /* Current driving strength 12 milli ampere */ +#define chipcHw_REG_CURRENT_MASK 0x00000007 /* Mask */ + /* Pins beyond 42 are defined by skipping 8 bits */ +#define chipcHw_REG_CURRENT(pin) (((pin) > 42) ? (&pChipcHw->GpioSR_0_7 + (((pin) + 2) >> 3)) : (&pChipcHw->GpioSR_0_7 + ((pin) >> 3))) +#define chipcHw_REG_CURRENT_POSITION(pin) (((pin) > 42) ? ((((pin) + 2) & 0x00000007) << 2) : (((pin) & 0x00000007) << 2)) + +#define chipcHw_REG_PULL_NONE 0x00000000 /* No pull up register */ +#define chipcHw_REG_PULL_UP 0x00000001 /* Pull up register enable */ +#define chipcHw_REG_PULL_DOWN 0x00000002 /* Pull down register enable */ +#define chipcHw_REG_PULLUP_MASK 0x00000003 /* Mask */ + /* Pins beyond 42 are defined by skipping 4 bits */ +#define chipcHw_REG_PULLUP(pin) (((pin) > 42) ? (&pChipcHw->GpioPull_0_15 + (((pin) + 2) >> 4)) : (&pChipcHw->GpioPull_0_15 + ((pin) >> 4))) +#define chipcHw_REG_PULLUP_POSITION(pin) (((pin) > 42) ? ((((pin) + 2) & 0x0000000F) << 1) : (((pin) & 0x0000000F) << 1)) + +#define chipcHw_REG_INPUTTYPE_CMOS 0x00000000 /* Normal CMOS logic */ +#define chipcHw_REG_INPUTTYPE_ST 0x00000001 /* High speed Schmitt Trigger */ +#define chipcHw_REG_INPUTTYPE_MASK 0x00000001 /* Mask */ + /* Pins beyond 42 are defined by skipping 2 bits */ +#define chipcHw_REG_INPUTTYPE(pin) (((pin) > 42) ? (&pChipcHw->GpioInput_0_31 + (((pin) + 2) >> 5)) : (&pChipcHw->GpioInput_0_31 + ((pin) >> 5))) +#define chipcHw_REG_INPUTTYPE_POSITION(pin) (((pin) > 42) ? ((((pin) + 2) & 0x0000001F)) : (((pin) & 0x0000001F))) + +/* Device connected to the bus clock */ +#define chipcHw_REG_BUS_CLOCK_ARM 0x00000001 /* Bus interface clock for ARM */ +#define chipcHw_REG_BUS_CLOCK_VDEC 0x00000002 /* Bus interface clock for VDEC */ +#define chipcHw_REG_BUS_CLOCK_ARAM 0x00000004 /* Bus interface clock for ARAM */ +#define chipcHw_REG_BUS_CLOCK_HPM 0x00000008 /* Bus interface clock for HPM */ +#define chipcHw_REG_BUS_CLOCK_DDRC 0x00000010 /* Bus interface clock for DDRC */ +#define chipcHw_REG_BUS_CLOCK_DMAC0 0x00000020 /* Bus interface clock for DMAC0 */ +#define chipcHw_REG_BUS_CLOCK_DMAC1 0x00000040 /* Bus interface clock for DMAC1 */ +#define chipcHw_REG_BUS_CLOCK_NVI 0x00000080 /* Bus interface clock for NVI */ +#define chipcHw_REG_BUS_CLOCK_ESW 0x00000100 /* Bus interface clock for ESW */ +#define chipcHw_REG_BUS_CLOCK_GE 0x00000200 /* Bus interface clock for GE */ +#define chipcHw_REG_BUS_CLOCK_I2CH 0x00000400 /* Bus interface clock for I2CH */ +#define chipcHw_REG_BUS_CLOCK_I2S0 0x00000800 /* Bus interface clock for I2S0 */ +#define chipcHw_REG_BUS_CLOCK_I2S1 0x00001000 /* Bus interface clock for I2S1 */ +#define chipcHw_REG_BUS_CLOCK_VRAM 0x00002000 /* Bus interface clock for VRAM */ +#define chipcHw_REG_BUS_CLOCK_CLCD 0x00004000 /* Bus interface clock for CLCD */ +#define chipcHw_REG_BUS_CLOCK_LDK 0x00008000 /* Bus interface clock for LDK */ +#define chipcHw_REG_BUS_CLOCK_LED 0x00010000 /* Bus interface clock for LED */ +#define chipcHw_REG_BUS_CLOCK_OTP 0x00020000 /* Bus interface clock for OTP */ +#define chipcHw_REG_BUS_CLOCK_PIF 0x00040000 /* Bus interface clock for PIF */ +#define chipcHw_REG_BUS_CLOCK_SPU 0x00080000 /* Bus interface clock for SPU */ +#define chipcHw_REG_BUS_CLOCK_SDIO0 0x00100000 /* Bus interface clock for SDIO0 */ +#define chipcHw_REG_BUS_CLOCK_SDIO1 0x00200000 /* Bus interface clock for SDIO1 */ +#define chipcHw_REG_BUS_CLOCK_SPIH 0x00400000 /* Bus interface clock for SPIH */ +#define chipcHw_REG_BUS_CLOCK_SPIS 0x00800000 /* Bus interface clock for SPIS */ +#define chipcHw_REG_BUS_CLOCK_UART0 0x01000000 /* Bus interface clock for UART0 */ +#define chipcHw_REG_BUS_CLOCK_UART1 0x02000000 /* Bus interface clock for UART1 */ +#define chipcHw_REG_BUS_CLOCK_BBL 0x04000000 /* Bus interface clock for BBL */ +#define chipcHw_REG_BUS_CLOCK_I2CS 0x08000000 /* Bus interface clock for I2CS */ +#define chipcHw_REG_BUS_CLOCK_USBH 0x10000000 /* Bus interface clock for USB Host */ +#define chipcHw_REG_BUS_CLOCK_USBD 0x20000000 /* Bus interface clock for USB Device */ +#define chipcHw_REG_BUS_CLOCK_BROM 0x40000000 /* Bus interface clock for Boot ROM */ +#define chipcHw_REG_BUS_CLOCK_TSC 0x80000000 /* Bus interface clock for Touch screen */ + +/* Software resets defines */ +#define chipcHw_REG_SOFT_RESET_VPM_GLOBAL_HOLD 0x0000000080000000ULL /* Reset Global VPM and hold */ +#define chipcHw_REG_SOFT_RESET_VPM_HOLD 0x0000000040000000ULL /* Reset VPM and hold */ +#define chipcHw_REG_SOFT_RESET_VPM_GLOBAL 0x0000000020000000ULL /* Reset Global VPM */ +#define chipcHw_REG_SOFT_RESET_VPM 0x0000000010000000ULL /* Reset VPM */ +#define chipcHw_REG_SOFT_RESET_KEYPAD 0x0000000008000000ULL /* Reset Key pad */ +#define chipcHw_REG_SOFT_RESET_LED 0x0000000004000000ULL /* Reset LED */ +#define chipcHw_REG_SOFT_RESET_SPU 0x0000000002000000ULL /* Reset SPU */ +#define chipcHw_REG_SOFT_RESET_RNG 0x0000000001000000ULL /* Reset RNG */ +#define chipcHw_REG_SOFT_RESET_PKA 0x0000000000800000ULL /* Reset PKA */ +#define chipcHw_REG_SOFT_RESET_LCD 0x0000000000400000ULL /* Reset LCD */ +#define chipcHw_REG_SOFT_RESET_PIF 0x0000000000200000ULL /* Reset PIF */ +#define chipcHw_REG_SOFT_RESET_I2CS 0x0000000000100000ULL /* Reset I2C Slave */ +#define chipcHw_REG_SOFT_RESET_I2CH 0x0000000000080000ULL /* Reset I2C Host */ +#define chipcHw_REG_SOFT_RESET_SDIO1 0x0000000000040000ULL /* Reset SDIO 1 */ +#define chipcHw_REG_SOFT_RESET_SDIO0 0x0000000000020000ULL /* Reset SDIO 0 */ +#define chipcHw_REG_SOFT_RESET_BBL 0x0000000000010000ULL /* Reset BBL */ +#define chipcHw_REG_SOFT_RESET_I2S1 0x0000000000008000ULL /* Reset I2S1 */ +#define chipcHw_REG_SOFT_RESET_I2S0 0x0000000000004000ULL /* Reset I2S0 */ +#define chipcHw_REG_SOFT_RESET_SPIS 0x0000000000002000ULL /* Reset SPI Slave */ +#define chipcHw_REG_SOFT_RESET_SPIH 0x0000000000001000ULL /* Reset SPI Host */ +#define chipcHw_REG_SOFT_RESET_GPIO1 0x0000000000000800ULL /* Reset GPIO block 1 */ +#define chipcHw_REG_SOFT_RESET_GPIO0 0x0000000000000400ULL /* Reset GPIO block 0 */ +#define chipcHw_REG_SOFT_RESET_UART1 0x0000000000000200ULL /* Reset UART 1 */ +#define chipcHw_REG_SOFT_RESET_UART0 0x0000000000000100ULL /* Reset UART 0 */ +#define chipcHw_REG_SOFT_RESET_NVI 0x0000000000000080ULL /* Reset NVI */ +#define chipcHw_REG_SOFT_RESET_WDOG 0x0000000000000040ULL /* Reset Watch dog */ +#define chipcHw_REG_SOFT_RESET_TMR 0x0000000000000020ULL /* Reset Timer */ +#define chipcHw_REG_SOFT_RESET_ETM 0x0000000000000010ULL /* Reset ETM */ +#define chipcHw_REG_SOFT_RESET_ARM_HOLD 0x0000000000000008ULL /* Reset ARM and HOLD */ +#define chipcHw_REG_SOFT_RESET_ARM 0x0000000000000004ULL /* Reset ARM */ +#define chipcHw_REG_SOFT_RESET_CHIP_WARM 0x0000000000000002ULL /* Chip warm reset */ +#define chipcHw_REG_SOFT_RESET_CHIP_SOFT 0x0000000000000001ULL /* Chip soft reset */ +#define chipcHw_REG_SOFT_RESET_VDEC 0x0000100000000000ULL /* Video decoder */ +#define chipcHw_REG_SOFT_RESET_GE 0x0000080000000000ULL /* Graphics engine */ +#define chipcHw_REG_SOFT_RESET_OTP 0x0000040000000000ULL /* Reset OTP */ +#define chipcHw_REG_SOFT_RESET_USB2 0x0000020000000000ULL /* Reset USB2 */ +#define chipcHw_REG_SOFT_RESET_USB1 0x0000010000000000ULL /* Reset USB 1 */ +#define chipcHw_REG_SOFT_RESET_USB 0x0000008000000000ULL /* Reset USB 1 and USB2 soft reset */ +#define chipcHw_REG_SOFT_RESET_ESW 0x0000004000000000ULL /* Reset Ethernet switch */ +#define chipcHw_REG_SOFT_RESET_ESWCLK 0x0000002000000000ULL /* Reset Ethernet switch clock */ +#define chipcHw_REG_SOFT_RESET_DDRPHY 0x0000001000000000ULL /* Reset DDR Physical */ +#define chipcHw_REG_SOFT_RESET_DDR 0x0000000800000000ULL /* Reset DDR Controller */ +#define chipcHw_REG_SOFT_RESET_TSC 0x0000000400000000ULL /* Reset Touch screen */ +#define chipcHw_REG_SOFT_RESET_PCM 0x0000000200000000ULL /* Reset PCM device */ +#define chipcHw_REG_SOFT_RESET_APM 0x0000200100000000ULL /* Reset APM device */ + +#define chipcHw_REG_SOFT_RESET_VPM_GLOBAL_UNHOLD 0x8000000000000000ULL /* Unhold Global VPM */ +#define chipcHw_REG_SOFT_RESET_VPM_UNHOLD 0x4000000000000000ULL /* Unhold VPM */ +#define chipcHw_REG_SOFT_RESET_ARM_UNHOLD 0x2000000000000000ULL /* Unhold ARM reset */ +#define chipcHw_REG_SOFT_RESET_UNHOLD_MASK 0xF000000000000000ULL /* Mask to handle unhold request */ + +/* Audio channel control defines */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_ALL 0x00000001 /* Enable all audio channel */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_A 0x00000002 /* Enable channel A */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_B 0x00000004 /* Enable channel B */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_C 0x00000008 /* Enable channel C */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_NTP_CLOCK 0x00000010 /* Enable NTP clock */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_PCM0_CLOCK 0x00000020 /* Enable PCM0 clock */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_PCM1_CLOCK 0x00000040 /* Enable PCM1 clock */ +#define chipcHw_REG_AUDIO_CHANNEL_ENABLE_APM_CLOCK 0x00000080 /* Enable APM clock */ + +/* Misc. chip control defines */ +#define chipcHw_REG_MISC_CTRL_GE_SEL 0x00040000 /* Select GE2/GE3 */ +#define chipcHw_REG_MISC_CTRL_I2S1_CLOCK_ONCHIP 0x00000000 /* Use on chip clock for I2S1 */ +#define chipcHw_REG_MISC_CTRL_I2S1_CLOCK_GPIO 0x00020000 /* Use external clock via GPIO pin 26 for I2S1 */ +#define chipcHw_REG_MISC_CTRL_I2S0_CLOCK_ONCHIP 0x00000000 /* Use on chip clock for I2S0 */ +#define chipcHw_REG_MISC_CTRL_I2S0_CLOCK_GPIO 0x00010000 /* Use external clock via GPIO pin 45 for I2S0 */ +#define chipcHw_REG_MISC_CTRL_ARM_CP15_DISABLE 0x00008000 /* Disable ARM CP15 bit */ +#define chipcHw_REG_MISC_CTRL_RTC_DISABLE 0x00000008 /* Disable RTC registers */ +#define chipcHw_REG_MISC_CTRL_BBRAM_DISABLE 0x00000004 /* Disable Battery Backed RAM */ +#define chipcHw_REG_MISC_CTRL_USB_MODE_HOST 0x00000002 /* Set USB as host */ +#define chipcHw_REG_MISC_CTRL_USB_MODE_DEVICE 0xFFFFFFFD /* Set USB as device */ +#define chipcHw_REG_MISC_CTRL_USB_POWERON 0xFFFFFFFE /* Power up USB */ +#define chipcHw_REG_MISC_CTRL_USB_POWEROFF 0x00000001 /* Power down USB */ + +/* OTP configuration defines */ +#define chipcHw_REG_OTP_SECURITY_OFF 0x0000020000000000ULL /* Security support is OFF */ +#define chipcHw_REG_OTP_SPU_SLOW 0x0000010000000000ULL /* Limited SPU throughput */ +#define chipcHw_REG_OTP_LCD_SPEED 0x0000000600000000ULL /* Set VPM speed one */ +#define chipcHw_REG_OTP_VPM_SPEED_1 0x0000000100000000ULL /* Set VPM speed one */ +#define chipcHw_REG_OTP_VPM_SPEED_0 0x0000000080000000ULL /* Set VPM speed zero */ +#define chipcHw_REG_OTP_AXI_SPEED 0x0000000060000000ULL /* Set maximum AXI bus speed */ +#define chipcHw_REG_OTP_APM_DISABLE 0x000000001F000000ULL /* Disable APM */ +#define chipcHw_REG_OTP_PIF_DISABLE 0x0000000000200000ULL /* Disable PIF */ +#define chipcHw_REG_OTP_VDEC_DISABLE 0x0000000000100000ULL /* Disable Video decoder */ +#define chipcHw_REG_OTP_BBL_DISABLE 0x0000000000080000ULL /* Disable RTC and BBRAM */ +#define chipcHw_REG_OTP_LED_DISABLE 0x0000000000040000ULL /* Disable LED */ +#define chipcHw_REG_OTP_GE_DISABLE 0x0000000000020000ULL /* Disable Graphics Engine */ +#define chipcHw_REG_OTP_LCD_DISABLE 0x0000000000010000ULL /* Disable LCD */ +#define chipcHw_REG_OTP_KEYPAD_DISABLE 0x0000000000008000ULL /* Disable keypad */ +#define chipcHw_REG_OTP_UART_DISABLE 0x0000000000004000ULL /* Disable UART */ +#define chipcHw_REG_OTP_SDIOH_DISABLE 0x0000000000003000ULL /* Disable SDIO host */ +#define chipcHw_REG_OTP_HSS_DISABLE 0x0000000000000C00ULL /* Disable HSS */ +#define chipcHw_REG_OTP_TSC_DISABLE 0x0000000000000200ULL /* Disable touch screen */ +#define chipcHw_REG_OTP_USB_DISABLE 0x0000000000000180ULL /* Disable USB */ +#define chipcHw_REG_OTP_SGMII_DISABLE 0x0000000000000060ULL /* Disable SGMII */ +#define chipcHw_REG_OTP_ETH_DISABLE 0x0000000000000018ULL /* Disable gigabit ethernet */ +#define chipcHw_REG_OTP_ETH_PHY_DISABLE 0x0000000000000006ULL /* Disable ethernet PHY */ +#define chipcHw_REG_OTP_VPM_DISABLE 0x0000000000000001ULL /* Disable VPM */ + +/* Sticky bit defines */ +#define chipcHw_REG_STICKY_BOOT_DONE 0x00000001 /* Boot done */ +#define chipcHw_REG_STICKY_SOFT_RESET 0x00000002 /* ARM soft reset */ +#define chipcHw_REG_STICKY_GENERAL_1 0x00000004 /* General purpose bit 1 */ +#define chipcHw_REG_STICKY_GENERAL_2 0x00000008 /* General purpose bit 2 */ +#define chipcHw_REG_STICKY_GENERAL_3 0x00000010 /* General purpose bit 3 */ +#define chipcHw_REG_STICKY_GENERAL_4 0x00000020 /* General purpose bit 4 */ +#define chipcHw_REG_STICKY_GENERAL_5 0x00000040 /* General purpose bit 5 */ +#define chipcHw_REG_STICKY_POR_BROM 0x00000080 /* Special sticky bit for security - set in BROM to avoid other modes being entered */ +#define chipcHw_REG_STICKY_ARM_RESET 0x00000100 /* ARM reset */ +#define chipcHw_REG_STICKY_CHIP_SOFT_RESET 0x00000200 /* Chip soft reset */ +#define chipcHw_REG_STICKY_CHIP_WARM_RESET 0x00000400 /* Chip warm reset */ +#define chipcHw_REG_STICKY_WDOG_RESET 0x00000800 /* Watchdog reset */ +#define chipcHw_REG_STICKY_OTP_RESET 0x00001000 /* OTP reset */ + + /* HW phase alignment defines *//* Spare1 register definitions */ +#define chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE 0x80000000 /* Enable DDR phase align panic interrupt */ +#define chipcHw_REG_SPARE1_VPM_PHASE_INTR_ENABLE 0x40000000 /* Enable VPM phase align panic interrupt */ +#define chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE 0x00000002 /* Enable access to VPM using system BUS */ +#define chipcHw_REG_SPARE1_DDR_BUS_ACCESS_ENABLE 0x00000001 /* Enable access to DDR using system BUS */ + /* DDRPhaseCtrl1 register definitions */ +#define chipcHw_REG_DDR_SW_PHASE_CTRL_ENABLE 0x80000000 /* Enable DDR SW phase alignment */ +#define chipcHw_REG_DDR_HW_PHASE_CTRL_ENABLE 0x40000000 /* Enable DDR HW phase alignment */ +#define chipcHw_REG_DDR_PHASE_VALUE_GE_MASK 0x0000007F /* DDR lower threshold for phase alignment */ +#define chipcHw_REG_DDR_PHASE_VALUE_GE_SHIFT 23 +#define chipcHw_REG_DDR_PHASE_VALUE_LE_MASK 0x0000007F /* DDR upper threshold for phase alignment */ +#define chipcHw_REG_DDR_PHASE_VALUE_LE_SHIFT 16 +#define chipcHw_REG_DDR_PHASE_ALIGN_WAIT_CYCLE_MASK 0x0000FFFF /* BUS Cycle to wait to run next DDR phase alignment */ +#define chipcHw_REG_DDR_PHASE_ALIGN_WAIT_CYCLE_SHIFT 0 + /* VPMPhaseCtrl1 register definitions */ +#define chipcHw_REG_VPM_SW_PHASE_CTRL_ENABLE 0x80000000 /* Enable VPM SW phase alignment */ +#define chipcHw_REG_VPM_HW_PHASE_CTRL_ENABLE 0x40000000 /* Enable VPM HW phase alignment */ +#define chipcHw_REG_VPM_PHASE_VALUE_GE_MASK 0x0000007F /* VPM lower threshold for phase alignment */ +#define chipcHw_REG_VPM_PHASE_VALUE_GE_SHIFT 23 +#define chipcHw_REG_VPM_PHASE_VALUE_LE_MASK 0x0000007F /* VPM upper threshold for phase alignment */ +#define chipcHw_REG_VPM_PHASE_VALUE_LE_SHIFT 16 +#define chipcHw_REG_VPM_PHASE_ALIGN_WAIT_CYCLE_MASK 0x0000FFFF /* BUS Cycle to wait to complete the VPM phase alignment */ +#define chipcHw_REG_VPM_PHASE_ALIGN_WAIT_CYCLE_SHIFT 0 + /* PhaseAlignStatus register definitions */ +#define chipcHw_REG_DDR_TIMEOUT_INTR_STATUS 0x80000000 /* DDR time out interrupt status */ +#define chipcHw_REG_DDR_PHASE_STATUS_MASK 0x0000007F /* DDR phase status value */ +#define chipcHw_REG_DDR_PHASE_STATUS_SHIFT 24 +#define chipcHw_REG_DDR_PHASE_ALIGNED 0x00800000 /* DDR Phase aligned status */ +#define chipcHw_REG_DDR_LOAD 0x00400000 /* Load DDR phase status */ +#define chipcHw_REG_DDR_PHASE_CTRL_MASK 0x0000003F /* DDR phase control value */ +#define chipcHw_REG_DDR_PHASE_CTRL_SHIFT 16 +#define chipcHw_REG_VPM_TIMEOUT_INTR_STATUS 0x80000000 /* VPM time out interrupt status */ +#define chipcHw_REG_VPM_PHASE_STATUS_MASK 0x0000007F /* VPM phase status value */ +#define chipcHw_REG_VPM_PHASE_STATUS_SHIFT 8 +#define chipcHw_REG_VPM_PHASE_ALIGNED 0x00000080 /* VPM Phase aligned status */ +#define chipcHw_REG_VPM_LOAD 0x00000040 /* Load VPM phase status */ +#define chipcHw_REG_VPM_PHASE_CTRL_MASK 0x0000003F /* VPM phase control value */ +#define chipcHw_REG_VPM_PHASE_CTRL_SHIFT 0 + /* DDRPhaseCtrl2 register definitions */ +#define chipcHw_REG_DDR_INTR_SERVICED 0x02000000 /* Acknowledge that interrupt was serviced */ +#define chipcHw_REG_DDR_TIMEOUT_INTR_ENABLE 0x01000000 /* Enable time out interrupt */ +#define chipcHw_REG_DDR_LOAD_COUNT_PHASE_CTRL_MASK 0x0000000F /* Wait before toggling load_ch */ +#define chipcHw_REG_DDR_LOAD_COUNT_PHASE_CTRL_SHIFT 20 +#define chipcHw_REG_DDR_TOTAL_LOAD_COUNT_CTRL_MASK 0x0000000F /* Total wait to settle ph_ctrl and load_ch */ +#define chipcHw_REG_DDR_TOTAL_LOAD_COUNT_CTRL_SHIFT 16 +#define chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_MASK 0x0000FFFF /* Time out value for DDR HW phase alignment */ +#define chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_SHIFT 0 + /* VPMPhaseCtrl2 register definitions */ +#define chipcHw_REG_VPM_INTR_SELECT_MASK 0x00000003 /* Interrupt select */ +#define chipcHw_REG_VPM_INTR_SELECT_SHIFT 26 +#define chipcHw_REG_VPM_INTR_DISABLE 0x00000000 +#define chipcHw_REG_VPM_INTR_FAST (0x1 << chipcHw_REG_VPM_INTR_SELECT_SHIFT) +#define chipcHw_REG_VPM_INTR_MEDIUM (0x2 << chipcHw_REG_VPM_INTR_SELECT_SHIFT) +#define chipcHw_REG_VPM_INTR_SLOW (0x3 << chipcHw_REG_VPM_INTR_SELECT_SHIFT) +#define chipcHw_REG_VPM_INTR_SERVICED 0x02000000 /* Acknowledge that interrupt was serviced */ +#define chipcHw_REG_VPM_TIMEOUT_INTR_ENABLE 0x01000000 /* Enable time out interrupt */ +#define chipcHw_REG_VPM_LOAD_COUNT_PHASE_CTRL_MASK 0x0000000F /* Wait before toggling load_ch */ +#define chipcHw_REG_VPM_LOAD_COUNT_PHASE_CTRL_SHIFT 20 +#define chipcHw_REG_VPM_TOTAL_LOAD_COUNT_CTRL_MASK 0x0000000F /* Total wait cycle to settle ph_ctrl and load_ch */ +#define chipcHw_REG_VPM_TOTAL_LOAD_COUNT_CTRL_SHIFT 16 +#define chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_MASK 0x0000FFFF /* Time out value for VPM HW phase alignment */ +#define chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_SHIFT 0 + +#endif /* CHIPCHW_REG_H */ -- GitLab From 2c4b57a204669a7b649f3eb891d3d0f0eba75321 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:05:37 +0100 Subject: [PATCH 0984/1002] ARM: 5655/1: bcmring: add csp chipc hardware definition file add csp chipc hardware definition file Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../include/mach/csp/chipcHw_def.h | 1123 +++++++++++++++++ 1 file changed, 1123 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h new file mode 100644 index 0000000000000..70eaea866cfee --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h @@ -0,0 +1,1123 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CHIPC_DEF_H +#define CHIPC_DEF_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include <csp/stdint.h> +#include <csp/errno.h> +#include <csp/reg.h> +#include <mach/csp/chipcHw_reg.h> + +/* ---- Public Constants and Types ---------------------------------------- */ + +/* Set 1 to configure DDR/VPM phase alignment by HW */ +#define chipcHw_DDR_HW_PHASE_ALIGN 0 +#define chipcHw_VPM_HW_PHASE_ALIGN 0 + +typedef uint32_t chipcHw_freq; + +/* Configurable miscellaneous clocks */ +typedef enum { + chipcHw_CLOCK_DDR, /* DDR PHY Clock */ + chipcHw_CLOCK_ARM, /* ARM Clock */ + chipcHw_CLOCK_ESW, /* Ethernet Switch Clock */ + chipcHw_CLOCK_VPM, /* VPM Clock */ + chipcHw_CLOCK_ESW125, /* Ethernet MII Clock */ + chipcHw_CLOCK_UART, /* UART Clock */ + chipcHw_CLOCK_SDIO0, /* SDIO 0 Clock */ + chipcHw_CLOCK_SDIO1, /* SDIO 1 Clock */ + chipcHw_CLOCK_SPI, /* SPI Clock */ + chipcHw_CLOCK_ETM, /* ARM ETM Clock */ + + chipcHw_CLOCK_BUS, /* BUS Clock */ + chipcHw_CLOCK_OTP, /* OTP Clock */ + chipcHw_CLOCK_I2C, /* I2C Host Clock */ + chipcHw_CLOCK_I2S0, /* I2S 0 Host Clock */ + chipcHw_CLOCK_RTBUS, /* DDR PHY Configuration Clock */ + chipcHw_CLOCK_APM100, /* APM100 Clock */ + chipcHw_CLOCK_TSC, /* Touch screen Clock */ + chipcHw_CLOCK_LED, /* LED Clock */ + + chipcHw_CLOCK_USB, /* USB Clock */ + chipcHw_CLOCK_LCD, /* LCD CLock */ + chipcHw_CLOCK_APM, /* APM Clock */ + + chipcHw_CLOCK_I2S1, /* I2S 1 Host Clock */ +} chipcHw_CLOCK_e; + +/* System booting strap options */ +typedef enum { + chipcHw_BOOT_DEVICE_UART = chipcHw_STRAPS_BOOT_DEVICE_UART, + chipcHw_BOOT_DEVICE_SERIAL_FLASH = + chipcHw_STRAPS_BOOT_DEVICE_SERIAL_FLASH, + chipcHw_BOOT_DEVICE_NOR_FLASH_16 = + chipcHw_STRAPS_BOOT_DEVICE_NOR_FLASH_16, + chipcHw_BOOT_DEVICE_NAND_FLASH_8 = + chipcHw_STRAPS_BOOT_DEVICE_NAND_FLASH_8, + chipcHw_BOOT_DEVICE_NAND_FLASH_16 = + chipcHw_STRAPS_BOOT_DEVICE_NAND_FLASH_16 +} chipcHw_BOOT_DEVICE_e; + +/* System booting modes */ +typedef enum { + chipcHw_BOOT_MODE_NORMAL = chipcHw_STRAPS_BOOT_MODE_NORMAL, + chipcHw_BOOT_MODE_DBG_SW = chipcHw_STRAPS_BOOT_MODE_DBG_SW, + chipcHw_BOOT_MODE_DBG_BOOT = chipcHw_STRAPS_BOOT_MODE_DBG_BOOT, + chipcHw_BOOT_MODE_NORMAL_QUIET = chipcHw_STRAPS_BOOT_MODE_NORMAL_QUIET +} chipcHw_BOOT_MODE_e; + +/* NAND Flash page size strap options */ +typedef enum { + chipcHw_NAND_PAGESIZE_512 = chipcHw_STRAPS_NAND_PAGESIZE_512, + chipcHw_NAND_PAGESIZE_2048 = chipcHw_STRAPS_NAND_PAGESIZE_2048, + chipcHw_NAND_PAGESIZE_4096 = chipcHw_STRAPS_NAND_PAGESIZE_4096, + chipcHw_NAND_PAGESIZE_EXT = chipcHw_STRAPS_NAND_PAGESIZE_EXT +} chipcHw_NAND_PAGESIZE_e; + +/* GPIO Pin function */ +typedef enum { + chipcHw_GPIO_FUNCTION_KEYPAD = chipcHw_REG_GPIO_MUX_KEYPAD, + chipcHw_GPIO_FUNCTION_I2CH = chipcHw_REG_GPIO_MUX_I2CH, + chipcHw_GPIO_FUNCTION_SPI = chipcHw_REG_GPIO_MUX_SPI, + chipcHw_GPIO_FUNCTION_UART = chipcHw_REG_GPIO_MUX_UART, + chipcHw_GPIO_FUNCTION_LEDMTXP = chipcHw_REG_GPIO_MUX_LEDMTXP, + chipcHw_GPIO_FUNCTION_LEDMTXS = chipcHw_REG_GPIO_MUX_LEDMTXS, + chipcHw_GPIO_FUNCTION_SDIO0 = chipcHw_REG_GPIO_MUX_SDIO0, + chipcHw_GPIO_FUNCTION_SDIO1 = chipcHw_REG_GPIO_MUX_SDIO1, + chipcHw_GPIO_FUNCTION_PCM = chipcHw_REG_GPIO_MUX_PCM, + chipcHw_GPIO_FUNCTION_I2S = chipcHw_REG_GPIO_MUX_I2S, + chipcHw_GPIO_FUNCTION_ETM = chipcHw_REG_GPIO_MUX_ETM, + chipcHw_GPIO_FUNCTION_DEBUG = chipcHw_REG_GPIO_MUX_DEBUG, + chipcHw_GPIO_FUNCTION_MISC = chipcHw_REG_GPIO_MUX_MISC, + chipcHw_GPIO_FUNCTION_GPIO = chipcHw_REG_GPIO_MUX_GPIO +} chipcHw_GPIO_FUNCTION_e; + +/* PIN Output slew rate */ +typedef enum { + chipcHw_PIN_SLEW_RATE_HIGH = chipcHw_REG_SLEW_RATE_HIGH, + chipcHw_PIN_SLEW_RATE_NORMAL = chipcHw_REG_SLEW_RATE_NORMAL +} chipcHw_PIN_SLEW_RATE_e; + +/* PIN Current drive strength */ +typedef enum { + chipcHw_PIN_CURRENT_STRENGTH_2mA = chipcHw_REG_CURRENT_STRENGTH_2mA, + chipcHw_PIN_CURRENT_STRENGTH_4mA = chipcHw_REG_CURRENT_STRENGTH_4mA, + chipcHw_PIN_CURRENT_STRENGTH_6mA = chipcHw_REG_CURRENT_STRENGTH_6mA, + chipcHw_PIN_CURRENT_STRENGTH_8mA = chipcHw_REG_CURRENT_STRENGTH_8mA, + chipcHw_PIN_CURRENT_STRENGTH_10mA = chipcHw_REG_CURRENT_STRENGTH_10mA, + chipcHw_PIN_CURRENT_STRENGTH_12mA = chipcHw_REG_CURRENT_STRENGTH_12mA +} chipcHw_PIN_CURRENT_STRENGTH_e; + +/* PIN Pull up register settings */ +typedef enum { + chipcHw_PIN_PULL_NONE = chipcHw_REG_PULL_NONE, + chipcHw_PIN_PULL_UP = chipcHw_REG_PULL_UP, + chipcHw_PIN_PULL_DOWN = chipcHw_REG_PULL_DOWN +} chipcHw_PIN_PULL_e; + +/* PIN input type settings */ +typedef enum { + chipcHw_PIN_INPUTTYPE_CMOS = chipcHw_REG_INPUTTYPE_CMOS, + chipcHw_PIN_INPUTTYPE_ST = chipcHw_REG_INPUTTYPE_ST +} chipcHw_PIN_INPUTTYPE_e; + +/* Allow/Disalow the support of spread spectrum */ +typedef enum { + chipcHw_SPREAD_SPECTRUM_DISALLOW, /* Spread spectrum support is not allowed */ + chipcHw_SPREAD_SPECTRUM_ALLOW /* Spread spectrum support is allowed */ +} chipcHw_SPREAD_SPECTRUM_e; + +typedef struct { + chipcHw_SPREAD_SPECTRUM_e ssSupport; /* Allow/Disalow to support spread spectrum. + If supported, call chipcHw_enableSpreadSpectrum () + to activate the spread spectrum with desired spread. */ + uint32_t pllVcoFreqHz; /* PLL VCO frequency in Hz */ + uint32_t pll2VcoFreqHz; /* PLL2 VCO frequency in Hz */ + uint32_t busClockFreqHz; /* Bus clock frequency in Hz */ + uint32_t armBusRatio; /* ARM clock : Bus clock */ + uint32_t vpmBusRatio; /* VPM clock : Bus clock */ + uint32_t ddrBusRatio; /* DDR clock : Bus clock */ +} chipcHw_INIT_PARAM_t; + +/* CHIP revision number */ +typedef enum { + chipcHw_REV_NUMBER_A0 = chipcHw_REG_REV_A0, + chipcHw_REV_NUMBER_B0 = chipcHw_REG_REV_B0 +} chipcHw_REV_NUMBER_e; + +typedef enum { + chipcHw_VPM_HW_PHASE_INTR_DISABLE = chipcHw_REG_VPM_INTR_DISABLE, + chipcHw_VPM_HW_PHASE_INTR_FAST = chipcHw_REG_VPM_INTR_FAST, + chipcHw_VPM_HW_PHASE_INTR_MEDIUM = chipcHw_REG_VPM_INTR_MEDIUM, + chipcHw_VPM_HW_PHASE_INTR_SLOW = chipcHw_REG_VPM_INTR_SLOW +} chipcHw_VPM_HW_PHASE_INTR_e; + +typedef enum { + chipcHw_DDR_HW_PHASE_MARGIN_STRICT, /* Strict margin for DDR phase align condition */ + chipcHw_DDR_HW_PHASE_MARGIN_MEDIUM, /* Medium margin for DDR phase align condition */ + chipcHw_DDR_HW_PHASE_MARGIN_WIDE /* Wider margin for DDR phase align condition */ +} chipcHw_DDR_HW_PHASE_MARGIN_e; + +typedef enum { + chipcHw_VPM_HW_PHASE_MARGIN_STRICT, /* Strict margin for VPM phase align condition */ + chipcHw_VPM_HW_PHASE_MARGIN_MEDIUM, /* Medium margin for VPM phase align condition */ + chipcHw_VPM_HW_PHASE_MARGIN_WIDE /* Wider margin for VPM phase align condition */ +} chipcHw_VPM_HW_PHASE_MARGIN_e; + +#define chipcHw_XTAL_FREQ_Hz 25000000 /* Reference clock frequency in Hz */ + +/* Programable pin defines */ +#define chipcHw_PIN_GPIO(n) ((((n) >= 0) && ((n) < (chipcHw_GPIO_COUNT))) ? (n) : 0xFFFFFFFF) + /* GPIO pin 0 - 60 */ +#define chipcHw_PIN_UARTTXD (chipcHw_GPIO_COUNT + 0) /* UART Transmit */ +#define chipcHw_PIN_NVI_A (chipcHw_GPIO_COUNT + 1) /* NVI Interface */ +#define chipcHw_PIN_NVI_D (chipcHw_GPIO_COUNT + 2) /* NVI Interface */ +#define chipcHw_PIN_NVI_OEB (chipcHw_GPIO_COUNT + 3) /* NVI Interface */ +#define chipcHw_PIN_NVI_WEB (chipcHw_GPIO_COUNT + 4) /* NVI Interface */ +#define chipcHw_PIN_NVI_CS (chipcHw_GPIO_COUNT + 5) /* NVI Interface */ +#define chipcHw_PIN_NVI_NAND_CSB (chipcHw_GPIO_COUNT + 6) /* NVI Interface */ +#define chipcHw_PIN_NVI_FLASHWP (chipcHw_GPIO_COUNT + 7) /* NVI Interface */ +#define chipcHw_PIN_NVI_NAND_RDYB (chipcHw_GPIO_COUNT + 8) /* NVI Interface */ +#define chipcHw_PIN_CL_DATA_0_17 (chipcHw_GPIO_COUNT + 9) /* LCD Data 0 - 17 */ +#define chipcHw_PIN_CL_DATA_18_20 (chipcHw_GPIO_COUNT + 10) /* LCD Data 18 - 20 */ +#define chipcHw_PIN_CL_DATA_21_23 (chipcHw_GPIO_COUNT + 11) /* LCD Data 21 - 23 */ +#define chipcHw_PIN_CL_POWER (chipcHw_GPIO_COUNT + 12) /* LCD Power */ +#define chipcHw_PIN_CL_ACK (chipcHw_GPIO_COUNT + 13) /* LCD Ack */ +#define chipcHw_PIN_CL_FP (chipcHw_GPIO_COUNT + 14) /* LCD FP */ +#define chipcHw_PIN_CL_LP (chipcHw_GPIO_COUNT + 15) /* LCD LP */ +#define chipcHw_PIN_UARTRXD (chipcHw_GPIO_COUNT + 16) /* UART Receive */ + +/* ---- Public Variable Externs ------------------------------------------ */ +/* ---- Public Function Prototypes --------------------------------------- */ + +/****************************************************************************/ +/** +* @brief Initializes the clock module +* +*/ +/****************************************************************************/ +void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam /* [ IN ] Misc chip initialization parameter */ + ) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Enables the PLL1 +* +* This function enables the PLL1 +* +*/ +/****************************************************************************/ +void chipcHw_pll1Enable(uint32_t vcoFreqHz, /* [ IN ] VCO frequency in Hz */ + chipcHw_SPREAD_SPECTRUM_e ssSupport /* [ IN ] SS status */ + ) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Enables the PLL2 +* +* This function enables the PLL2 +* +*/ +/****************************************************************************/ +void chipcHw_pll2Enable(uint32_t vcoFreqHz /* [ IN ] VCO frequency in Hz */ + ) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Disable the PLL1 +* +*/ +/****************************************************************************/ +static inline void chipcHw_pll1Disable(void); + +/****************************************************************************/ +/** +* @brief Disable the PLL2 +* +*/ +/****************************************************************************/ +static inline void chipcHw_pll2Disable(void); + +/****************************************************************************/ +/** +* @brief Set clock fequency for miscellaneous configurable clocks +* +* This function sets clock frequency +* +* @return Configured clock frequency in KHz +* +*/ +/****************************************************************************/ +chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Set clock fequency for miscellaneous configurable clocks +* +* This function sets clock frequency +* +* @return Configured clock frequency in Hz +* +*/ +/****************************************************************************/ +chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock, /* [ IN ] Configurable clock */ + uint32_t freq /* [ IN ] Clock frequency in Hz */ + ) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Set VPM clock in sync with BUS clock +* +* This function does the phase adjustment between VPM and BUS clock +* +* @return >= 0 : On success ( # of adjustment required ) +* -1 : On failure +*/ +/****************************************************************************/ +int chipcHw_vpmPhaseAlign(void); + +/****************************************************************************/ +/** +* @brief Enables core a clock of a certain device +* +* This function enables a core clock +* +* @return void +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_setClockEnable(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ); + +/****************************************************************************/ +/** +* @brief Disabled a core clock of a certain device +* +* This function disables a core clock +* +* @return void +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_setClockDisable(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ); + +/****************************************************************************/ +/** +* @brief Enables bypass clock of a certain device +* +* This function enables bypass clock +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_bypassClockEnable(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ); + +/****************************************************************************/ +/** +* @brief Disabled bypass clock of a certain device +* +* This function disables bypass clock +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_bypassClockDisable(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ); + +/****************************************************************************/ +/** +* @brief Get Numeric Chip ID +* +* This function returns Chip ID that includes the revison number +* +* @return Complete numeric Chip ID +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getChipId(void); + +/****************************************************************************/ +/** +* @brief Get Chip Product ID +* +* This function returns Chip Product ID +* +* @return Chip Product ID +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getChipProductId(void); + +/****************************************************************************/ +/** +* @brief Get revision number +* +* This function returns revision number of the chip +* +* @return Revision number +*/ +/****************************************************************************/ +static inline chipcHw_REV_NUMBER_e chipcHw_getChipRevisionNumber(void); + +/****************************************************************************/ +/** +* @brief Enables bus interface clock +* +* Enables bus interface clock of various device +* +* @return void +* +* @note use chipcHw_REG_BUS_CLOCK_XXXX +*/ +/****************************************************************************/ +static inline void chipcHw_busInterfaceClockEnable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_BUS_CLOCK_XXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Disables bus interface clock +* +* Disables bus interface clock of various device +* +* @return void +* +* @note use chipcHw_REG_BUS_CLOCK_XXXX +*/ +/****************************************************************************/ +static inline void chipcHw_busInterfaceClockDisable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_BUS_CLOCK_XXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Enables various audio channels +* +* Enables audio channel +* +* @return void +* +* @note use chipcHw_REG_AUDIO_CHANNEL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_audioChannelEnable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_AUDIO_CHANNEL_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Disables various audio channels +* +* Disables audio channel +* +* @return void +* +* @note use chipcHw_REG_AUDIO_CHANNEL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_audioChannelDisable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_AUDIO_CHANNEL_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Soft resets devices +* +* Soft resets various devices +* +* @return void +* +* @note use chipcHw_REG_SOFT_RESET_XXXXXX defines +*/ +/****************************************************************************/ +static inline void chipcHw_softReset(uint64_t mask /* [ IN ] Bit map of type chipcHw_REG_SOFT_RESET_XXXXXX */ + ); + +static inline void chipcHw_softResetDisable(uint64_t mask /* [ IN ] Bit map of type chipcHw_REG_SOFT_RESET_XXXXXX */ + ); + +static inline void chipcHw_softResetEnable(uint64_t mask /* [ IN ] Bit map of type chipcHw_REG_SOFT_RESET_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Configures misc CHIP functionality +* +* Configures CHIP functionality +* +* @return void +* +* @note use chipcHw_REG_MISC_CTRL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_miscControl(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_MISC_CTRL_XXXXXX */ + ); + +static inline void chipcHw_miscControlDisable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_MISC_CTRL_XXXXXX */ + ); + +static inline void chipcHw_miscControlEnable(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_MISC_CTRL_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Set OTP options +* +* Set OTP options +* +* @return void +* +* @note use chipcHw_REG_OTP_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_setOTPOption(uint64_t mask /* [ IN ] Bit map of type chipcHw_REG_OTP_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Get sticky bits +* +* @return Sticky bit options of type chipcHw_REG_STICKY_XXXXXX +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getStickyBits(void); + +/****************************************************************************/ +/** +* @brief Set sticky bits +* +* @return void +* +* @note use chipcHw_REG_STICKY_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_setStickyBits(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_STICKY_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Clear sticky bits +* +* @return void +* +* @note use chipcHw_REG_STICKY_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_clearStickyBits(uint32_t mask /* [ IN ] Bit map of type chipcHw_REG_STICKY_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Get software override strap options +* +* Retrieves software override strap options +* +* @return Software override strap value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getSoftStraps(void); + +/****************************************************************************/ +/** +* @brief Set software override strap options +* +* set software override strap options +* +* @return nothing +* +*/ +/****************************************************************************/ +static inline void chipcHw_setSoftStraps(uint32_t strapOptions); + +/****************************************************************************/ +/** +* @brief Get pin strap options +* +* Retrieves pin strap options +* +* @return Pin strap value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getPinStraps(void); + +/****************************************************************************/ +/** +* @brief Get valid pin strap options +* +* Retrieves valid pin strap options +* +* @return valid Pin strap value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getValidStraps(void); + +/****************************************************************************/ +/** +* @brief Initialize valid pin strap options +* +* Retrieves valid pin strap options by copying HW strap options to soft register +* (if chipcHw_STRAPS_SOFT_OVERRIDE not set) +* +* @return nothing +* +*/ +/****************************************************************************/ +static inline void chipcHw_initValidStraps(void); + +/****************************************************************************/ +/** +* @brief Get status (enabled/disabled) of bus interface clock +* +* This function returns the status of devices' bus interface clock +* +* @return Bus interface clock +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getBusInterfaceClockStatus(void); + +/****************************************************************************/ +/** +* @brief Get boot device +* +* This function returns the device type used in booting the system +* +* @return Boot device of type chipcHw_BOOT_DEVICE_e +* +*/ +/****************************************************************************/ +static inline chipcHw_BOOT_DEVICE_e chipcHw_getBootDevice(void); + +/****************************************************************************/ +/** +* @brief Get boot mode +* +* This function returns the way the system was booted +* +* @return Boot mode of type chipcHw_BOOT_MODE_e +* +*/ +/****************************************************************************/ +static inline chipcHw_BOOT_MODE_e chipcHw_getBootMode(void); + +/****************************************************************************/ +/** +* @brief Get NAND flash page size +* +* This function returns the NAND device page size +* +* @return Boot NAND device page size +* +*/ +/****************************************************************************/ +static inline chipcHw_NAND_PAGESIZE_e chipcHw_getNandPageSize(void); + +/****************************************************************************/ +/** +* @brief Get NAND flash address cycle configuration +* +* This function returns the NAND flash address cycle configuration +* +* @return 0 = Do not extra address cycle, 1 = Add extra cycle +* +*/ +/****************************************************************************/ +static inline int chipcHw_getNandExtraCycle(void); + +/****************************************************************************/ +/** +* @brief Activates PIF interface +* +* This function activates PIF interface by taking control of LCD pins +* +* @note +* When activated, LCD pins will be defined as follows for PIF operation +* +* CLD[17:0] = pif_data[17:0] +* CLD[23:18] = pif_address[5:0] +* CLPOWER = pif_wr_str +* CLCP = pif_rd_str +* CLAC = pif_hat1 +* CLFP = pif_hrdy1 +* CLLP = pif_hat2 +* GPIO[42] = pif_hrdy2 +* +* In PIF mode, "pif_hrdy2" overrides other shared function for GPIO[42] pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_activatePifInterface(void); + +/****************************************************************************/ +/** +* @brief Activates LCD interface +* +* This function activates LCD interface +* +* @note +* When activated, LCD pins will be defined as follows +* +* CLD[17:0] = LCD data +* CLD[23:18] = LCD data +* CLPOWER = LCD power +* CLCP = +* CLAC = LCD ack +* CLFP = +* CLLP = +*/ +/****************************************************************************/ +static inline void chipcHw_activateLcdInterface(void); + +/****************************************************************************/ +/** +* @brief Deactivates PIF/LCD interface +* +* This function deactivates PIF/LCD interface +* +* @note +* When deactivated LCD pins will be in rti-stated +* +*/ +/****************************************************************************/ +static inline void chipcHw_deactivatePifLcdInterface(void); + +/****************************************************************************/ +/** +* @brief Get to know the configuration of GPIO pin +* +*/ +/****************************************************************************/ +static inline chipcHw_GPIO_FUNCTION_e chipcHw_getGpioPinFunction(int pin /* GPIO Pin number */ + ); + +/****************************************************************************/ +/** +* @brief Configure GPIO pin function +* +*/ +/****************************************************************************/ +static inline void chipcHw_setGpioPinFunction(int pin, /* GPIO Pin number */ + chipcHw_GPIO_FUNCTION_e func /* Configuration function */ + ); + +/****************************************************************************/ +/** +* @brief Set Pin slew rate +* +* This function sets the slew of individual pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinSlewRate(uint32_t pin, /* Pin of type chipcHw_PIN_XXXXX */ + chipcHw_PIN_SLEW_RATE_e slewRate /* Pin slew rate */ + ); + +/****************************************************************************/ +/** +* @brief Set Pin output drive current +* +* This function sets output drive current of individual pin +* +* Note: Avoid the use of the word 'current' since linux headers define this +* to be the current task. +*/ +/****************************************************************************/ +static inline void chipcHw_setPinOutputCurrent(uint32_t pin, /* Pin of type chipcHw_PIN_XXXXX */ + chipcHw_PIN_CURRENT_STRENGTH_e curr /* Pin current rating */ + ); + +/****************************************************************************/ +/** +* @brief Set Pin pullup register +* +* This function sets pullup register of individual pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinPullup(uint32_t pin, /* Pin of type chipcHw_PIN_XXXXX */ + chipcHw_PIN_PULL_e pullup /* Pullup register settings */ + ); + +/****************************************************************************/ +/** +* @brief Set Pin input type +* +* This function sets input type of individual Pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinInputType(uint32_t pin, /* Pin of type chipcHw_PIN_XXXXX */ + chipcHw_PIN_INPUTTYPE_e inputType /* Pin input type */ + ); + +/****************************************************************************/ +/** +* @brief Retrieves a string representation of the mux setting for a pin. +* +* @return Pointer to a character string. +*/ +/****************************************************************************/ + +const char *chipcHw_getGpioPinFunctionStr(int pin); + +/****************************************************************************/ +/** @brief issue warmReset + */ +/****************************************************************************/ +void chipcHw_reset(uint32_t mask); + +/****************************************************************************/ +/** @brief clock reconfigure + */ +/****************************************************************************/ +void chipcHw_clockReconfig(uint32_t busHz, uint32_t armRatio, uint32_t vpmRatio, + uint32_t ddrRatio); + +/****************************************************************************/ +/** +* @brief Enable Spread Spectrum +* +* @note chipcHw_Init() must be called earlier +*/ +/****************************************************************************/ +static inline void chipcHw_enableSpreadSpectrum(void); + +/****************************************************************************/ +/** +* @brief Disable Spread Spectrum +* +*/ +/****************************************************************************/ +static inline void chipcHw_disableSpreadSpectrum(void); + +/****************************************************************************/ +/** @brief Checks if software strap is enabled + * + * @return 1 : When enable + * 0 : When disable + */ +/****************************************************************************/ +static inline int chipcHw_isSoftwareStrapsEnable(void); + +/****************************************************************************/ +/** @brief Enable software strap + */ +/****************************************************************************/ +static inline void chipcHw_softwareStrapsEnable(void); + +/****************************************************************************/ +/** @brief Disable software strap + */ +/****************************************************************************/ +static inline void chipcHw_softwareStrapsDisable(void); + +/****************************************************************************/ +/** @brief PLL test enable + */ +/****************************************************************************/ +static inline void chipcHw_pllTestEnable(void); + +/****************************************************************************/ +/** @brief PLL2 test enable + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestEnable(void); + +/****************************************************************************/ +/** @brief PLL test disable + */ +/****************************************************************************/ +static inline void chipcHw_pllTestDisable(void); + +/****************************************************************************/ +/** @brief PLL2 test disable + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestDisable(void); + +/****************************************************************************/ +/** @brief Get PLL test status + */ +/****************************************************************************/ +static inline int chipcHw_isPllTestEnable(void); + +/****************************************************************************/ +/** @brief Get PLL2 test status + */ +/****************************************************************************/ +static inline int chipcHw_isPll2TestEnable(void); + +/****************************************************************************/ +/** @brief PLL test select + */ +/****************************************************************************/ +static inline void chipcHw_pllTestSelect(uint32_t val); + +/****************************************************************************/ +/** @brief PLL2 test select + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestSelect(uint32_t val); + +/****************************************************************************/ +/** @brief Get PLL test selected option + */ +/****************************************************************************/ +static inline uint8_t chipcHw_getPllTestSelected(void); + +/****************************************************************************/ +/** @brief Get PLL2 test selected option + */ +/****************************************************************************/ +static inline uint8_t chipcHw_getPll2TestSelected(void); + +/****************************************************************************/ +/** +* @brief Enables DDR SW phase alignment interrupt +*/ +/****************************************************************************/ +static inline void chipcHw_ddrPhaseAlignInterruptEnable(void); + +/****************************************************************************/ +/** +* @brief Disables DDR SW phase alignment interrupt +*/ +/****************************************************************************/ +static inline void chipcHw_ddrPhaseAlignInterruptDisable(void); + +/****************************************************************************/ +/** +* @brief Set VPM SW phase alignment interrupt mode +* +* This function sets VPM phase alignment interrupt +* +*/ +/****************************************************************************/ +static inline void +chipcHw_vpmPhaseAlignInterruptMode(chipcHw_VPM_HW_PHASE_INTR_e mode); + +/****************************************************************************/ +/** +* @brief Enable DDR phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrSwPhaseAlignEnable(void); + +/****************************************************************************/ +/** +* @brief Disable DDR phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrSwPhaseAlignDisable(void); + +/****************************************************************************/ +/** +* @brief Enable DDR phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignEnable(void); + +/****************************************************************************/ +/** +* @brief Disable DDR phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignDisable(void); + +/****************************************************************************/ +/** +* @brief Enable VPM phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmSwPhaseAlignEnable(void); + +/****************************************************************************/ +/** +* @brief Disable VPM phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmSwPhaseAlignDisable(void); + +/****************************************************************************/ +/** +* @brief Enable VPM phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignEnable(void); + +/****************************************************************************/ +/** +* @brief Disable VPM phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignDisable(void); + +/****************************************************************************/ +/** +* @brief Set DDR phase alignment margin in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_setDdrHwPhaseAlignMargin(chipcHw_DDR_HW_PHASE_MARGIN_e margin /* Margin alinging DDR phase */ + ); + +/****************************************************************************/ +/** +* @brief Set VPM phase alignment margin in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_setVpmHwPhaseAlignMargin(chipcHw_VPM_HW_PHASE_MARGIN_e margin /* Margin alinging VPM phase */ + ); + +/****************************************************************************/ +/** +* @brief Checks DDR phase aligned status done by HW +* +* @return 1: When aligned +* 0: When not aligned +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_isDdrHwPhaseAligned(void); + +/****************************************************************************/ +/** +* @brief Checks VPM phase aligned status done by HW +* +* @return 1: When aligned +* 0: When not aligned +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_isVpmHwPhaseAligned(void); + +/****************************************************************************/ +/** +* @brief Get DDR phase aligned status done by HW +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getDdrHwPhaseAlignStatus(void); + +/****************************************************************************/ +/** +* @brief Get VPM phase aligned status done by HW +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getVpmHwPhaseAlignStatus(void); + +/****************************************************************************/ +/** +* @brief Get DDR phase control value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getDdrPhaseControl(void); + +/****************************************************************************/ +/** +* @brief Get VPM phase control value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getVpmPhaseControl(void); + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout count +* +* @note If HW fails to perform the phase alignment, it will trigger +* a DDR phase alignment timeout interrupt. +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeout(uint32_t busCycle /* Timeout in bus cycle */ + ); + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout count +* +* @note If HW fails to perform the phase alignment, it will trigger +* a VPM phase alignment timeout interrupt. +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeout(uint32_t busCycle /* Timeout in bus cycle */ + ); + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout interrupt enable +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptEnable(void); + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout interrupt enable +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptEnable(void); + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout interrupt disable +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptDisable(void); + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout interrupt disable +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptDisable(void); + +/****************************************************************************/ +/** +* @brief Clear DDR phase alignment timeout interrupt +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptClear(void); + +/****************************************************************************/ +/** +* @brief Clear VPM phase alignment timeout interrupt +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptClear(void); + +/* ---- Private Constants and Types -------------------------------------- */ + +#endif /* CHIPC_DEF_H */ -- GitLab From 4818a4727d787b2da0dc73c66f04d241626f4c97 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:06:13 +0100 Subject: [PATCH 0985/1002] ARM: 5656/1: bcmring: add csp chipc inline functions add csp chipc inline functions Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- .../include/mach/csp/chipcHw_inline.h | 1673 +++++++++++++++++ 1 file changed, 1673 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h new file mode 100644 index 0000000000000..c78833acb37aa --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h @@ -0,0 +1,1673 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#ifndef CHIPC_INLINE_H +#define CHIPC_INLINE_H + +/* ---- Include Files ----------------------------------------------------- */ + +#include <csp/errno.h> +#include <csp/reg.h> +#include <mach/csp/chipcHw_reg.h> +#include <mach/csp/chipcHw_def.h> + +/* ---- Private Constants and Types --------------------------------------- */ +typedef enum { + chipcHw_OPTYPE_BYPASS, /* Bypass operation */ + chipcHw_OPTYPE_OUTPUT /* Output operation */ +} chipcHw_OPTYPE_e; + +/* ---- Public Constants and Types ---------------------------------------- */ +/* ---- Public Variable Externs ------------------------------------------- */ +/* ---- Public Function Prototypes ---------------------------------------- */ +/* ---- Private Function Prototypes --------------------------------------- */ +static inline void chipcHw_setClock(chipcHw_CLOCK_e clock, + chipcHw_OPTYPE_e type, int mode); + +/****************************************************************************/ +/** +* @brief Get Numeric Chip ID +* +* This function returns Chip ID that includes the revison number +* +* @return Complete numeric Chip ID +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getChipId(void) +{ + return pChipcHw->ChipId; +} + +/****************************************************************************/ +/** +* @brief Enable Spread Spectrum +* +* @note chipcHw_Init() must be called earlier +*/ +/****************************************************************************/ +static inline void chipcHw_enableSpreadSpectrum(void) +{ + if ((pChipcHw-> + PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != + chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) { + ddrcReg_PHY_ADDR_CTL_REGP->ssCfg = + (0xFFFF << ddrcReg_PHY_ADDR_SS_CFG_NDIV_AMPLITUDE_SHIFT) | + (ddrcReg_PHY_ADDR_SS_CFG_MIN_CYCLE_PER_TICK << + ddrcReg_PHY_ADDR_SS_CFG_CYCLE_PER_TICK_SHIFT); + ddrcReg_PHY_ADDR_CTL_REGP->ssCtl |= + ddrcReg_PHY_ADDR_SS_CTRL_ENABLE; + } +} + +/****************************************************************************/ +/** +* @brief Disable Spread Spectrum +* +*/ +/****************************************************************************/ +static inline void chipcHw_disableSpreadSpectrum(void) +{ + ddrcReg_PHY_ADDR_CTL_REGP->ssCtl &= ~ddrcReg_PHY_ADDR_SS_CTRL_ENABLE; +} + +/****************************************************************************/ +/** +* @brief Get Chip Product ID +* +* This function returns Chip Product ID +* +* @return Chip Product ID +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getChipProductId(void) +{ + return (pChipcHw-> + ChipId & chipcHw_REG_CHIPID_BASE_MASK) >> + chipcHw_REG_CHIPID_BASE_SHIFT; +} + +/****************************************************************************/ +/** +* @brief Get revision number +* +* This function returns revision number of the chip +* +* @return Revision number +*/ +/****************************************************************************/ +static inline chipcHw_REV_NUMBER_e chipcHw_getChipRevisionNumber(void) +{ + return pChipcHw->ChipId & chipcHw_REG_CHIPID_REV_MASK; +} + +/****************************************************************************/ +/** +* @brief Enables bus interface clock +* +* Enables bus interface clock of various device +* +* @return void +* +* @note use chipcHw_REG_BUS_CLOCK_XXXX for mask +*/ +/****************************************************************************/ +static inline void chipcHw_busInterfaceClockEnable(uint32_t mask) +{ + reg32_modify_or(&pChipcHw->BusIntfClock, mask); +} + +/****************************************************************************/ +/** +* @brief Disables bus interface clock +* +* Disables bus interface clock of various device +* +* @return void +* +* @note use chipcHw_REG_BUS_CLOCK_XXXX +*/ +/****************************************************************************/ +static inline void chipcHw_busInterfaceClockDisable(uint32_t mask) +{ + reg32_modify_and(&pChipcHw->BusIntfClock, ~mask); +} + +/****************************************************************************/ +/** +* @brief Get status (enabled/disabled) of bus interface clock +* +* This function returns the status of devices' bus interface clock +* +* @return Bus interface clock +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getBusInterfaceClockStatus(void) +{ + return pChipcHw->BusIntfClock; +} + +/****************************************************************************/ +/** +* @brief Enables various audio channels +* +* Enables audio channel +* +* @return void +* +* @note use chipcHw_REG_AUDIO_CHANNEL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_audioChannelEnable(uint32_t mask) +{ + reg32_modify_or(&pChipcHw->AudioEnable, mask); +} + +/****************************************************************************/ +/** +* @brief Disables various audio channels +* +* Disables audio channel +* +* @return void +* +* @note use chipcHw_REG_AUDIO_CHANNEL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_audioChannelDisable(uint32_t mask) +{ + reg32_modify_and(&pChipcHw->AudioEnable, ~mask); +} + +/****************************************************************************/ +/** +* @brief Soft resets devices +* +* Soft resets various devices +* +* @return void +* +* @note use chipcHw_REG_SOFT_RESET_XXXXXX defines +*/ +/****************************************************************************/ +static inline void chipcHw_softReset(uint64_t mask) +{ + chipcHw_softResetEnable(mask); + chipcHw_softResetDisable(mask); +} + +static inline void chipcHw_softResetDisable(uint64_t mask) +{ + uint32_t ctrl1 = (uint32_t) mask; + uint32_t ctrl2 = (uint32_t) (mask >> 32); + + /* Deassert module soft reset */ + REG_LOCAL_IRQ_SAVE; + pChipcHw->SoftReset1 ^= ctrl1; + pChipcHw->SoftReset2 ^= (ctrl2 & (~chipcHw_REG_SOFT_RESET_UNHOLD_MASK)); + REG_LOCAL_IRQ_RESTORE; +} + +static inline void chipcHw_softResetEnable(uint64_t mask) +{ + uint32_t ctrl1 = (uint32_t) mask; + uint32_t ctrl2 = (uint32_t) (mask >> 32); + uint32_t unhold = 0; + + REG_LOCAL_IRQ_SAVE; + pChipcHw->SoftReset1 |= ctrl1; + /* Mask out unhold request bits */ + pChipcHw->SoftReset2 |= (ctrl2 & (~chipcHw_REG_SOFT_RESET_UNHOLD_MASK)); + + /* Process unhold requests */ + if (ctrl2 & chipcHw_REG_SOFT_RESET_VPM_GLOBAL_UNHOLD) { + unhold = chipcHw_REG_SOFT_RESET_VPM_GLOBAL_HOLD; + } + + if (ctrl2 & chipcHw_REG_SOFT_RESET_VPM_UNHOLD) { + unhold |= chipcHw_REG_SOFT_RESET_VPM_HOLD; + } + + if (ctrl2 & chipcHw_REG_SOFT_RESET_ARM_UNHOLD) { + unhold |= chipcHw_REG_SOFT_RESET_ARM_HOLD; + } + + if (unhold) { + /* Make sure unhold request is effective */ + pChipcHw->SoftReset1 &= ~unhold; + } + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Configures misc CHIP functionality +* +* Configures CHIP functionality +* +* @return void +* +* @note use chipcHw_REG_MISC_CTRL_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_miscControl(uint32_t mask) +{ + reg32_write(&pChipcHw->MiscCtrl, mask); +} + +static inline void chipcHw_miscControlDisable(uint32_t mask) +{ + reg32_modify_and(&pChipcHw->MiscCtrl, ~mask); +} + +static inline void chipcHw_miscControlEnable(uint32_t mask) +{ + reg32_modify_or(&pChipcHw->MiscCtrl, mask); +} + +/****************************************************************************/ +/** +* @brief Set OTP options +* +* Set OTP options +* +* @return void +* +* @note use chipcHw_REG_OTP_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_setOTPOption(uint64_t mask) +{ + uint32_t ctrl1 = (uint32_t) mask; + uint32_t ctrl2 = (uint32_t) (mask >> 32); + + reg32_modify_or(&pChipcHw->SoftOTP1, ctrl1); + reg32_modify_or(&pChipcHw->SoftOTP2, ctrl2); +} + +/****************************************************************************/ +/** +* @brief Get sticky bits +* +* @return Sticky bit options of type chipcHw_REG_STICKY_XXXXXX +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getStickyBits(void) +{ + return pChipcHw->Sticky; +} + +/****************************************************************************/ +/** +* @brief Set sticky bits +* +* @return void +* +* @note use chipcHw_REG_STICKY_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_setStickyBits(uint32_t mask) +{ + uint32_t bits = 0; + + REG_LOCAL_IRQ_SAVE; + if (mask & chipcHw_REG_STICKY_POR_BROM) { + bits |= chipcHw_REG_STICKY_POR_BROM; + } else { + uint32_t sticky; + sticky = pChipcHw->Sticky; + + if ((mask & chipcHw_REG_STICKY_BOOT_DONE) + && (sticky & chipcHw_REG_STICKY_BOOT_DONE) == 0) { + bits |= chipcHw_REG_STICKY_BOOT_DONE; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_1) + && (sticky & chipcHw_REG_STICKY_GENERAL_1) == 0) { + bits |= chipcHw_REG_STICKY_GENERAL_1; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_2) + && (sticky & chipcHw_REG_STICKY_GENERAL_2) == 0) { + bits |= chipcHw_REG_STICKY_GENERAL_2; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_3) + && (sticky & chipcHw_REG_STICKY_GENERAL_3) == 0) { + bits |= chipcHw_REG_STICKY_GENERAL_3; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_4) + && (sticky & chipcHw_REG_STICKY_GENERAL_4) == 0) { + bits |= chipcHw_REG_STICKY_GENERAL_4; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_5) + && (sticky & chipcHw_REG_STICKY_GENERAL_5) == 0) { + bits |= chipcHw_REG_STICKY_GENERAL_5; + } + } + pChipcHw->Sticky = bits; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Clear sticky bits +* +* @return void +* +* @note use chipcHw_REG_STICKY_XXXXXX +*/ +/****************************************************************************/ +static inline void chipcHw_clearStickyBits(uint32_t mask) +{ + uint32_t bits = 0; + + REG_LOCAL_IRQ_SAVE; + if (mask & + (chipcHw_REG_STICKY_BOOT_DONE | chipcHw_REG_STICKY_GENERAL_1 | + chipcHw_REG_STICKY_GENERAL_2 | chipcHw_REG_STICKY_GENERAL_3 | + chipcHw_REG_STICKY_GENERAL_4 | chipcHw_REG_STICKY_GENERAL_5)) { + uint32_t sticky = pChipcHw->Sticky; + + if ((mask & chipcHw_REG_STICKY_BOOT_DONE) + && (sticky & chipcHw_REG_STICKY_BOOT_DONE)) { + bits = chipcHw_REG_STICKY_BOOT_DONE; + mask &= ~chipcHw_REG_STICKY_BOOT_DONE; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_1) + && (sticky & chipcHw_REG_STICKY_GENERAL_1)) { + bits |= chipcHw_REG_STICKY_GENERAL_1; + mask &= ~chipcHw_REG_STICKY_GENERAL_1; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_2) + && (sticky & chipcHw_REG_STICKY_GENERAL_2)) { + bits |= chipcHw_REG_STICKY_GENERAL_2; + mask &= ~chipcHw_REG_STICKY_GENERAL_2; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_3) + && (sticky & chipcHw_REG_STICKY_GENERAL_3)) { + bits |= chipcHw_REG_STICKY_GENERAL_3; + mask &= ~chipcHw_REG_STICKY_GENERAL_3; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_4) + && (sticky & chipcHw_REG_STICKY_GENERAL_4)) { + bits |= chipcHw_REG_STICKY_GENERAL_4; + mask &= ~chipcHw_REG_STICKY_GENERAL_4; + } + if ((mask & chipcHw_REG_STICKY_GENERAL_5) + && (sticky & chipcHw_REG_STICKY_GENERAL_5)) { + bits |= chipcHw_REG_STICKY_GENERAL_5; + mask &= ~chipcHw_REG_STICKY_GENERAL_5; + } + } + pChipcHw->Sticky = bits | mask; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Get software strap value +* +* Retrieves software strap value +* +* @return Software strap value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getSoftStraps(void) +{ + return pChipcHw->SoftStraps; +} + +/****************************************************************************/ +/** +* @brief Set software override strap options +* +* set software override strap options +* +* @return nothing +* +*/ +/****************************************************************************/ +static inline void chipcHw_setSoftStraps(uint32_t strapOptions) +{ + reg32_write(&pChipcHw->SoftStraps, strapOptions); +} + +/****************************************************************************/ +/** +* @brief Get Pin Strap Options +* +* This function returns the raw boot strap options +* +* @return strap options +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getPinStraps(void) +{ + return pChipcHw->PinStraps; +} + +/****************************************************************************/ +/** +* @brief Get Valid Strap Options +* +* This function returns the valid raw boot strap options +* +* @return strap options +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getValidStraps(void) +{ + uint32_t softStraps; + + /* + ** Always return the SoftStraps - bootROM calls chipcHw_initValidStraps + ** which copies HW straps to soft straps if there is no override + */ + softStraps = chipcHw_getSoftStraps(); + + return softStraps; +} + +/****************************************************************************/ +/** +* @brief Initialize valid pin strap options +* +* Retrieves valid pin strap options by copying HW strap options to soft register +* (if chipcHw_STRAPS_SOFT_OVERRIDE not set) +* +* @return nothing +* +*/ +/****************************************************************************/ +static inline void chipcHw_initValidStraps(void) +{ + uint32_t softStraps; + + REG_LOCAL_IRQ_SAVE; + softStraps = chipcHw_getSoftStraps(); + + if ((softStraps & chipcHw_STRAPS_SOFT_OVERRIDE) == 0) { + /* Copy HW straps to software straps */ + chipcHw_setSoftStraps(chipcHw_getPinStraps()); + } + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Get boot device +* +* This function returns the device type used in booting the system +* +* @return Boot device of type chipcHw_BOOT_DEVICE +* +*/ +/****************************************************************************/ +static inline chipcHw_BOOT_DEVICE_e chipcHw_getBootDevice(void) +{ + return chipcHw_getValidStraps() & chipcHw_STRAPS_BOOT_DEVICE_MASK; +} + +/****************************************************************************/ +/** +* @brief Get boot mode +* +* This function returns the way the system was booted +* +* @return Boot mode of type chipcHw_BOOT_MODE +* +*/ +/****************************************************************************/ +static inline chipcHw_BOOT_MODE_e chipcHw_getBootMode(void) +{ + return chipcHw_getValidStraps() & chipcHw_STRAPS_BOOT_MODE_MASK; +} + +/****************************************************************************/ +/** +* @brief Get NAND flash page size +* +* This function returns the NAND device page size +* +* @return Boot NAND device page size +* +*/ +/****************************************************************************/ +static inline chipcHw_NAND_PAGESIZE_e chipcHw_getNandPageSize(void) +{ + return chipcHw_getValidStraps() & chipcHw_STRAPS_NAND_PAGESIZE_MASK; +} + +/****************************************************************************/ +/** +* @brief Get NAND flash address cycle configuration +* +* This function returns the NAND flash address cycle configuration +* +* @return 0 = Do not extra address cycle, 1 = Add extra cycle +* +*/ +/****************************************************************************/ +static inline int chipcHw_getNandExtraCycle(void) +{ + if (chipcHw_getValidStraps() & chipcHw_STRAPS_NAND_EXTRA_CYCLE) { + return 1; + } else { + return 0; + } +} + +/****************************************************************************/ +/** +* @brief Activates PIF interface +* +* This function activates PIF interface by taking control of LCD pins +* +* @note +* When activated, LCD pins will be defined as follows for PIF operation +* +* CLD[17:0] = pif_data[17:0] +* CLD[23:18] = pif_address[5:0] +* CLPOWER = pif_wr_str +* CLCP = pif_rd_str +* CLAC = pif_hat1 +* CLFP = pif_hrdy1 +* CLLP = pif_hat2 +* GPIO[42] = pif_hrdy2 +* +* In PIF mode, "pif_hrdy2" overrides other shared function for GPIO[42] pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_activatePifInterface(void) +{ + reg32_write(&pChipcHw->LcdPifMode, chipcHw_REG_PIF_PIN_ENABLE); +} + +/****************************************************************************/ +/** +* @brief Activates LCD interface +* +* This function activates LCD interface +* +* @note +* When activated, LCD pins will be defined as follows +* +* CLD[17:0] = LCD data +* CLD[23:18] = LCD data +* CLPOWER = LCD power +* CLCP = +* CLAC = LCD ack +* CLFP = +* CLLP = +*/ +/****************************************************************************/ +static inline void chipcHw_activateLcdInterface(void) +{ + reg32_write(&pChipcHw->LcdPifMode, chipcHw_REG_LCD_PIN_ENABLE); +} + +/****************************************************************************/ +/** +* @brief Deactivates PIF/LCD interface +* +* This function deactivates PIF/LCD interface +* +* @note +* When deactivated LCD pins will be in rti-stated +* +*/ +/****************************************************************************/ +static inline void chipcHw_deactivatePifLcdInterface(void) +{ + reg32_write(&pChipcHw->LcdPifMode, 0); +} + +/****************************************************************************/ +/** +* @brief Select GE2 +* +* This function select GE2 as the graphic engine +* +*/ +/****************************************************************************/ +static inline void chipcHw_selectGE2(void) +{ + reg32_modify_and(&pChipcHw->MiscCtrl, ~chipcHw_REG_MISC_CTRL_GE_SEL); +} + +/****************************************************************************/ +/** +* @brief Select GE3 +* +* This function select GE3 as the graphic engine +* +*/ +/****************************************************************************/ +static inline void chipcHw_selectGE3(void) +{ + reg32_modify_or(&pChipcHw->MiscCtrl, chipcHw_REG_MISC_CTRL_GE_SEL); +} + +/****************************************************************************/ +/** +* @brief Get to know the configuration of GPIO pin +* +*/ +/****************************************************************************/ +static inline chipcHw_GPIO_FUNCTION_e chipcHw_getGpioPinFunction(int pin) +{ + return (*((uint32_t *) chipcHw_REG_GPIO_MUX(pin)) & + (chipcHw_REG_GPIO_MUX_MASK << + chipcHw_REG_GPIO_MUX_POSITION(pin))) >> + chipcHw_REG_GPIO_MUX_POSITION(pin); +} + +/****************************************************************************/ +/** +* @brief Configure GPIO pin function +* +*/ +/****************************************************************************/ +static inline void chipcHw_setGpioPinFunction(int pin, + chipcHw_GPIO_FUNCTION_e func) +{ + REG_LOCAL_IRQ_SAVE; + *((uint32_t *) chipcHw_REG_GPIO_MUX(pin)) &= + ~(chipcHw_REG_GPIO_MUX_MASK << chipcHw_REG_GPIO_MUX_POSITION(pin)); + *((uint32_t *) chipcHw_REG_GPIO_MUX(pin)) |= + func << chipcHw_REG_GPIO_MUX_POSITION(pin); + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set Pin slew rate +* +* This function sets the slew of individual pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinSlewRate(uint32_t pin, + chipcHw_PIN_SLEW_RATE_e slewRate) +{ + REG_LOCAL_IRQ_SAVE; + *((uint32_t *) chipcHw_REG_SLEW_RATE(pin)) &= + ~(chipcHw_REG_SLEW_RATE_MASK << + chipcHw_REG_SLEW_RATE_POSITION(pin)); + *((uint32_t *) chipcHw_REG_SLEW_RATE(pin)) |= + (uint32_t) slewRate << chipcHw_REG_SLEW_RATE_POSITION(pin); + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set Pin output drive current +* +* This function sets output drive current of individual pin +* +* Note: Avoid the use of the word 'current' since linux headers define this +* to be the current task. +*/ +/****************************************************************************/ +static inline void chipcHw_setPinOutputCurrent(uint32_t pin, + chipcHw_PIN_CURRENT_STRENGTH_e + curr) +{ + REG_LOCAL_IRQ_SAVE; + *((uint32_t *) chipcHw_REG_CURRENT(pin)) &= + ~(chipcHw_REG_CURRENT_MASK << chipcHw_REG_CURRENT_POSITION(pin)); + *((uint32_t *) chipcHw_REG_CURRENT(pin)) |= + (uint32_t) curr << chipcHw_REG_CURRENT_POSITION(pin); + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set Pin pullup register +* +* This function sets pullup register of individual pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinPullup(uint32_t pin, chipcHw_PIN_PULL_e pullup) +{ + REG_LOCAL_IRQ_SAVE; + *((uint32_t *) chipcHw_REG_PULLUP(pin)) &= + ~(chipcHw_REG_PULLUP_MASK << chipcHw_REG_PULLUP_POSITION(pin)); + *((uint32_t *) chipcHw_REG_PULLUP(pin)) |= + (uint32_t) pullup << chipcHw_REG_PULLUP_POSITION(pin); + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set Pin input type +* +* This function sets input type of individual pin +* +*/ +/****************************************************************************/ +static inline void chipcHw_setPinInputType(uint32_t pin, + chipcHw_PIN_INPUTTYPE_e inputType) +{ + REG_LOCAL_IRQ_SAVE; + *((uint32_t *) chipcHw_REG_INPUTTYPE(pin)) &= + ~(chipcHw_REG_INPUTTYPE_MASK << + chipcHw_REG_INPUTTYPE_POSITION(pin)); + *((uint32_t *) chipcHw_REG_INPUTTYPE(pin)) |= + (uint32_t) inputType << chipcHw_REG_INPUTTYPE_POSITION(pin); + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Power up the USB PHY +* +* This function powers up the USB PHY +* +*/ +/****************************************************************************/ +static inline void chipcHw_powerUpUsbPhy(void) +{ + reg32_modify_and(&pChipcHw->MiscCtrl, + chipcHw_REG_MISC_CTRL_USB_POWERON); +} + +/****************************************************************************/ +/** +* @brief Power down the USB PHY +* +* This function powers down the USB PHY +* +*/ +/****************************************************************************/ +static inline void chipcHw_powerDownUsbPhy(void) +{ + reg32_modify_or(&pChipcHw->MiscCtrl, + chipcHw_REG_MISC_CTRL_USB_POWEROFF); +} + +/****************************************************************************/ +/** +* @brief Set the 2nd USB as host +* +* This function sets the 2nd USB as host +* +*/ +/****************************************************************************/ +static inline void chipcHw_setUsbHost(void) +{ + reg32_modify_or(&pChipcHw->MiscCtrl, + chipcHw_REG_MISC_CTRL_USB_MODE_HOST); +} + +/****************************************************************************/ +/** +* @brief Set the 2nd USB as device +* +* This function sets the 2nd USB as device +* +*/ +/****************************************************************************/ +static inline void chipcHw_setUsbDevice(void) +{ + reg32_modify_and(&pChipcHw->MiscCtrl, + chipcHw_REG_MISC_CTRL_USB_MODE_DEVICE); +} + +/****************************************************************************/ +/** +* @brief Lower layer funtion to enable/disable a clock of a certain device +* +* This function enables/disables a core clock +* +*/ +/****************************************************************************/ +static inline void chipcHw_setClock(chipcHw_CLOCK_e clock, + chipcHw_OPTYPE_e type, int mode) +{ + volatile uint32_t *pPLLReg = (uint32_t *) 0x0; + volatile uint32_t *pClockCtrl = (uint32_t *) 0x0; + + switch (clock) { + case chipcHw_CLOCK_DDR: + pPLLReg = &pChipcHw->DDRClock; + break; + case chipcHw_CLOCK_ARM: + pPLLReg = &pChipcHw->ARMClock; + break; + case chipcHw_CLOCK_ESW: + pPLLReg = &pChipcHw->ESWClock; + break; + case chipcHw_CLOCK_VPM: + pPLLReg = &pChipcHw->VPMClock; + break; + case chipcHw_CLOCK_ESW125: + pPLLReg = &pChipcHw->ESW125Clock; + break; + case chipcHw_CLOCK_UART: + pPLLReg = &pChipcHw->UARTClock; + break; + case chipcHw_CLOCK_SDIO0: + pPLLReg = &pChipcHw->SDIO0Clock; + break; + case chipcHw_CLOCK_SDIO1: + pPLLReg = &pChipcHw->SDIO1Clock; + break; + case chipcHw_CLOCK_SPI: + pPLLReg = &pChipcHw->SPIClock; + break; + case chipcHw_CLOCK_ETM: + pPLLReg = &pChipcHw->ETMClock; + break; + case chipcHw_CLOCK_USB: + pPLLReg = &pChipcHw->USBClock; + if (type == chipcHw_OPTYPE_OUTPUT) { + if (mode) { + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } else { + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } + } + break; + case chipcHw_CLOCK_LCD: + pPLLReg = &pChipcHw->LCDClock; + if (type == chipcHw_OPTYPE_OUTPUT) { + if (mode) { + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } else { + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } + } + break; + case chipcHw_CLOCK_APM: + pPLLReg = &pChipcHw->APMClock; + if (type == chipcHw_OPTYPE_OUTPUT) { + if (mode) { + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } else { + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_POWER_DOWN); + } + } + break; + case chipcHw_CLOCK_BUS: + pClockCtrl = &pChipcHw->ACLKClock; + break; + case chipcHw_CLOCK_OTP: + pClockCtrl = &pChipcHw->OTPClock; + break; + case chipcHw_CLOCK_I2C: + pClockCtrl = &pChipcHw->I2CClock; + break; + case chipcHw_CLOCK_I2S0: + pClockCtrl = &pChipcHw->I2S0Clock; + break; + case chipcHw_CLOCK_RTBUS: + pClockCtrl = &pChipcHw->RTBUSClock; + break; + case chipcHw_CLOCK_APM100: + pClockCtrl = &pChipcHw->APM100Clock; + break; + case chipcHw_CLOCK_TSC: + pClockCtrl = &pChipcHw->TSCClock; + break; + case chipcHw_CLOCK_LED: + pClockCtrl = &pChipcHw->LEDClock; + break; + case chipcHw_CLOCK_I2S1: + pClockCtrl = &pChipcHw->I2S1Clock; + break; + } + + if (pPLLReg) { + switch (type) { + case chipcHw_OPTYPE_OUTPUT: + /* PLL clock output enable/disable */ + if (mode) { + if (clock == chipcHw_CLOCK_DDR) { + /* DDR clock enable is inverted */ + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_OUTPUT_ENABLE); + } else { + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_OUTPUT_ENABLE); + } + } else { + if (clock == chipcHw_CLOCK_DDR) { + /* DDR clock disable is inverted */ + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_OUTPUT_ENABLE); + } else { + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_OUTPUT_ENABLE); + } + } + break; + case chipcHw_OPTYPE_BYPASS: + /* PLL clock bypass enable/disable */ + if (mode) { + reg32_modify_or(pPLLReg, + chipcHw_REG_PLL_CLOCK_BYPASS_SELECT); + } else { + reg32_modify_and(pPLLReg, + ~chipcHw_REG_PLL_CLOCK_BYPASS_SELECT); + } + break; + } + } else if (pClockCtrl) { + switch (type) { + case chipcHw_OPTYPE_OUTPUT: + if (mode) { + reg32_modify_or(pClockCtrl, + chipcHw_REG_DIV_CLOCK_OUTPUT_ENABLE); + } else { + reg32_modify_and(pClockCtrl, + ~chipcHw_REG_DIV_CLOCK_OUTPUT_ENABLE); + } + break; + case chipcHw_OPTYPE_BYPASS: + if (mode) { + reg32_modify_or(pClockCtrl, + chipcHw_REG_DIV_CLOCK_BYPASS_SELECT); + } else { + reg32_modify_and(pClockCtrl, + ~chipcHw_REG_DIV_CLOCK_BYPASS_SELECT); + } + break; + } + } +} + +/****************************************************************************/ +/** +* @brief Disables a core clock of a certain device +* +* This function disables a core clock +* +* @note no change in power consumption +*/ +/****************************************************************************/ +static inline void chipcHw_setClockDisable(chipcHw_CLOCK_e clock) +{ + + /* Disable output of the clock */ + chipcHw_setClock(clock, chipcHw_OPTYPE_OUTPUT, 0); +} + +/****************************************************************************/ +/** +* @brief Enable a core clock of a certain device +* +* This function enables a core clock +* +* @note no change in power consumption +*/ +/****************************************************************************/ +static inline void chipcHw_setClockEnable(chipcHw_CLOCK_e clock) +{ + + /* Enable output of the clock */ + chipcHw_setClock(clock, chipcHw_OPTYPE_OUTPUT, 1); +} + +/****************************************************************************/ +/** +* @brief Enables bypass clock of a certain device +* +* This function enables bypass clock +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_bypassClockEnable(chipcHw_CLOCK_e clock) +{ + /* Enable bypass clock */ + chipcHw_setClock(clock, chipcHw_OPTYPE_BYPASS, 1); +} + +/****************************************************************************/ +/** +* @brief Disabled bypass clock of a certain device +* +* This function disables bypass clock +* +* @note Doesnot affect the bus interface clock +*/ +/****************************************************************************/ +static inline void chipcHw_bypassClockDisable(chipcHw_CLOCK_e clock) +{ + /* Disable bypass clock */ + chipcHw_setClock(clock, chipcHw_OPTYPE_BYPASS, 0); + +} + +/****************************************************************************/ +/** @brief Checks if software strap is enabled + * + * @return 1 : When enable + * 0 : When disable + */ +/****************************************************************************/ +static inline int chipcHw_isSoftwareStrapsEnable(void) +{ + return pChipcHw->SoftStraps & 0x00000001; +} + +/****************************************************************************/ +/** @brief Enable software strap + */ +/****************************************************************************/ +static inline void chipcHw_softwareStrapsEnable(void) +{ + reg32_modify_or(&pChipcHw->SoftStraps, 0x00000001); +} + +/****************************************************************************/ +/** @brief Disable software strap + */ +/****************************************************************************/ +static inline void chipcHw_softwareStrapsDisable(void) +{ + reg32_modify_and(&pChipcHw->SoftStraps, (~0x00000001)); +} + +/****************************************************************************/ +/** @brief PLL test enable + */ +/****************************************************************************/ +static inline void chipcHw_pllTestEnable(void) +{ + reg32_modify_or(&pChipcHw->PLLConfig, + chipcHw_REG_PLL_CONFIG_TEST_ENABLE); +} + +/****************************************************************************/ +/** @brief PLL2 test enable + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestEnable(void) +{ + reg32_modify_or(&pChipcHw->PLLConfig2, + chipcHw_REG_PLL_CONFIG_TEST_ENABLE); +} + +/****************************************************************************/ +/** @brief PLL test disable + */ +/****************************************************************************/ +static inline void chipcHw_pllTestDisable(void) +{ + reg32_modify_and(&pChipcHw->PLLConfig, + ~chipcHw_REG_PLL_CONFIG_TEST_ENABLE); +} + +/****************************************************************************/ +/** @brief PLL2 test disable + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestDisable(void) +{ + reg32_modify_and(&pChipcHw->PLLConfig2, + ~chipcHw_REG_PLL_CONFIG_TEST_ENABLE); +} + +/****************************************************************************/ +/** @brief Get PLL test status + */ +/****************************************************************************/ +static inline int chipcHw_isPllTestEnable(void) +{ + return pChipcHw->PLLConfig & chipcHw_REG_PLL_CONFIG_TEST_ENABLE; +} + +/****************************************************************************/ +/** @brief Get PLL2 test status + */ +/****************************************************************************/ +static inline int chipcHw_isPll2TestEnable(void) +{ + return pChipcHw->PLLConfig2 & chipcHw_REG_PLL_CONFIG_TEST_ENABLE; +} + +/****************************************************************************/ +/** @brief PLL test select + */ +/****************************************************************************/ +static inline void chipcHw_pllTestSelect(uint32_t val) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK; + pChipcHw->PLLConfig |= + (val) << chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** @brief PLL2 test select + */ +/****************************************************************************/ +static inline void chipcHw_pll2TestSelect(uint32_t val) +{ + + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK; + pChipcHw->PLLConfig2 |= + (val) << chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** @brief Get PLL test selected option + */ +/****************************************************************************/ +static inline uint8_t chipcHw_getPllTestSelected(void) +{ + return (uint8_t) ((pChipcHw-> + PLLConfig & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK) + >> chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT); +} + +/****************************************************************************/ +/** @brief Get PLL2 test selected option + */ +/****************************************************************************/ +static inline uint8_t chipcHw_getPll2TestSelected(void) +{ + return (uint8_t) ((pChipcHw-> + PLLConfig2 & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK) + >> chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT); +} + +/****************************************************************************/ +/** +* @brief Disable the PLL1 +* +*/ +/****************************************************************************/ +static inline void chipcHw_pll1Disable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig |= chipcHw_REG_PLL_CONFIG_POWER_DOWN; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disable the PLL2 +* +*/ +/****************************************************************************/ +static inline void chipcHw_pll2Disable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig2 |= chipcHw_REG_PLL_CONFIG_POWER_DOWN; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Enables DDR SW phase alignment interrupt +*/ +/****************************************************************************/ +static inline void chipcHw_ddrPhaseAlignInterruptEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->Spare1 |= chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disables DDR SW phase alignment interrupt +*/ +/****************************************************************************/ +static inline void chipcHw_ddrPhaseAlignInterruptDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set VPM SW phase alignment interrupt mode +* +* This function sets VPM phase alignment interrupt +*/ +/****************************************************************************/ +static inline void +chipcHw_vpmPhaseAlignInterruptMode(chipcHw_VPM_HW_PHASE_INTR_e mode) +{ + REG_LOCAL_IRQ_SAVE; + if (mode == chipcHw_VPM_HW_PHASE_INTR_DISABLE) { + pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_PHASE_INTR_ENABLE; + } else { + pChipcHw->Spare1 |= chipcHw_REG_SPARE1_VPM_PHASE_INTR_ENABLE; + } + pChipcHw->VPMPhaseCtrl2 = + (pChipcHw-> + VPMPhaseCtrl2 & ~(chipcHw_REG_VPM_INTR_SELECT_MASK << + chipcHw_REG_VPM_INTR_SELECT_SHIFT)) | mode; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Enable DDR phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrSwPhaseAlignEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl1 |= chipcHw_REG_DDR_SW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disable DDR phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrSwPhaseAlignDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl1 &= ~chipcHw_REG_DDR_SW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Enable DDR phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl1 |= chipcHw_REG_DDR_HW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disable DDR phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl1 &= ~chipcHw_REG_DDR_HW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Enable VPM phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmSwPhaseAlignEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl1 |= chipcHw_REG_VPM_SW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disable VPM phase alignment in software +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmSwPhaseAlignDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl1 &= ~chipcHw_REG_VPM_SW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Enable VPM phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl1 |= chipcHw_REG_VPM_HW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Disable VPM phase alignment in hardware +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl1 &= ~chipcHw_REG_VPM_HW_PHASE_CTRL_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Set DDR phase alignment margin in hardware +* +*/ +/****************************************************************************/ +static inline void +chipcHw_setDdrHwPhaseAlignMargin(chipcHw_DDR_HW_PHASE_MARGIN_e margin) +{ + uint32_t ge = 0; + uint32_t le = 0; + + switch (margin) { + case chipcHw_DDR_HW_PHASE_MARGIN_STRICT: + ge = 0x0F; + le = 0x0F; + break; + case chipcHw_DDR_HW_PHASE_MARGIN_MEDIUM: + ge = 0x03; + le = 0x3F; + break; + case chipcHw_DDR_HW_PHASE_MARGIN_WIDE: + ge = 0x01; + le = 0x7F; + break; + } + + { + REG_LOCAL_IRQ_SAVE; + + pChipcHw->DDRPhaseCtrl1 &= + ~((chipcHw_REG_DDR_PHASE_VALUE_GE_MASK << + chipcHw_REG_DDR_PHASE_VALUE_GE_SHIFT) + || (chipcHw_REG_DDR_PHASE_VALUE_LE_MASK << + chipcHw_REG_DDR_PHASE_VALUE_LE_SHIFT)); + + pChipcHw->DDRPhaseCtrl1 |= + ((ge << chipcHw_REG_DDR_PHASE_VALUE_GE_SHIFT) + || (le << chipcHw_REG_DDR_PHASE_VALUE_LE_SHIFT)); + + REG_LOCAL_IRQ_RESTORE; + } +} + +/****************************************************************************/ +/** +* @brief Set VPM phase alignment margin in hardware +* +*/ +/****************************************************************************/ +static inline void +chipcHw_setVpmHwPhaseAlignMargin(chipcHw_VPM_HW_PHASE_MARGIN_e margin) +{ + uint32_t ge = 0; + uint32_t le = 0; + + switch (margin) { + case chipcHw_VPM_HW_PHASE_MARGIN_STRICT: + ge = 0x0F; + le = 0x0F; + break; + case chipcHw_VPM_HW_PHASE_MARGIN_MEDIUM: + ge = 0x03; + le = 0x3F; + break; + case chipcHw_VPM_HW_PHASE_MARGIN_WIDE: + ge = 0x01; + le = 0x7F; + break; + } + + { + REG_LOCAL_IRQ_SAVE; + + pChipcHw->VPMPhaseCtrl1 &= + ~((chipcHw_REG_VPM_PHASE_VALUE_GE_MASK << + chipcHw_REG_VPM_PHASE_VALUE_GE_SHIFT) + || (chipcHw_REG_VPM_PHASE_VALUE_LE_MASK << + chipcHw_REG_VPM_PHASE_VALUE_LE_SHIFT)); + + pChipcHw->VPMPhaseCtrl1 |= + ((ge << chipcHw_REG_VPM_PHASE_VALUE_GE_SHIFT) + || (le << chipcHw_REG_VPM_PHASE_VALUE_LE_SHIFT)); + + REG_LOCAL_IRQ_RESTORE; + } +} + +/****************************************************************************/ +/** +* @brief Checks DDR phase aligned status done by HW +* +* @return 1: When aligned +* 0: When not aligned +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_isDdrHwPhaseAligned(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_DDR_PHASE_ALIGNED) ? 1 : 0; +} + +/****************************************************************************/ +/** +* @brief Checks VPM phase aligned status done by HW +* +* @return 1: When aligned +* 0: When not aligned +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_isVpmHwPhaseAligned(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_VPM_PHASE_ALIGNED) ? 1 : 0; +} + +/****************************************************************************/ +/** +* @brief Get DDR phase aligned status done by HW +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getDdrHwPhaseAlignStatus(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_DDR_PHASE_STATUS_MASK) >> + chipcHw_REG_DDR_PHASE_STATUS_SHIFT; +} + +/****************************************************************************/ +/** +* @brief Get VPM phase aligned status done by HW +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getVpmHwPhaseAlignStatus(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_VPM_PHASE_STATUS_MASK) >> + chipcHw_REG_VPM_PHASE_STATUS_SHIFT; +} + +/****************************************************************************/ +/** +* @brief Get DDR phase control value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getDdrPhaseControl(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_DDR_PHASE_CTRL_MASK) >> + chipcHw_REG_DDR_PHASE_CTRL_SHIFT; +} + +/****************************************************************************/ +/** +* @brief Get VPM phase control value +* +*/ +/****************************************************************************/ +static inline uint32_t chipcHw_getVpmPhaseControl(void) +{ + return (pChipcHw-> + PhaseAlignStatus & chipcHw_REG_VPM_PHASE_CTRL_MASK) >> + chipcHw_REG_VPM_PHASE_CTRL_SHIFT; +} + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout count +* +* @note If HW fails to perform the phase alignment, it will trigger +* a DDR phase alignment timeout interrupt. +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeout(uint32_t busCycle) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl2 &= + ~(chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_MASK << + chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_SHIFT); + pChipcHw->DDRPhaseCtrl2 |= + (busCycle & chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_MASK) << + chipcHw_REG_DDR_PHASE_TIMEOUT_COUNT_SHIFT; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout count +* +* @note If HW fails to perform the phase alignment, it will trigger +* a VPM phase alignment timeout interrupt. +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeout(uint32_t busCycle) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl2 &= + ~(chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_MASK << + chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_SHIFT); + pChipcHw->VPMPhaseCtrl2 |= + (busCycle & chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_MASK) << + chipcHw_REG_VPM_PHASE_TIMEOUT_COUNT_SHIFT; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Clear DDR phase alignment timeout interrupt +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptClear(void) +{ + REG_LOCAL_IRQ_SAVE; + /* Clear timeout interrupt service bit */ + pChipcHw->DDRPhaseCtrl2 |= chipcHw_REG_DDR_INTR_SERVICED; + pChipcHw->DDRPhaseCtrl2 &= ~chipcHw_REG_DDR_INTR_SERVICED; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief Clear VPM phase alignment timeout interrupt +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptClear(void) +{ + REG_LOCAL_IRQ_SAVE; + /* Clear timeout interrupt service bit */ + pChipcHw->VPMPhaseCtrl2 |= chipcHw_REG_VPM_INTR_SERVICED; + pChipcHw->VPMPhaseCtrl2 &= ~chipcHw_REG_VPM_INTR_SERVICED; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout interrupt enable +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + chipcHw_ddrHwPhaseAlignTimeoutInterruptClear(); /* Recommended */ + /* Enable timeout interrupt */ + pChipcHw->DDRPhaseCtrl2 |= chipcHw_REG_DDR_TIMEOUT_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout interrupt enable +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptEnable(void) +{ + REG_LOCAL_IRQ_SAVE; + chipcHw_vpmHwPhaseAlignTimeoutInterruptClear(); /* Recommended */ + /* Enable timeout interrupt */ + pChipcHw->VPMPhaseCtrl2 |= chipcHw_REG_VPM_TIMEOUT_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief DDR phase alignment timeout interrupt disable +* +*/ +/****************************************************************************/ +static inline void chipcHw_ddrHwPhaseAlignTimeoutInterruptDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->DDRPhaseCtrl2 &= ~chipcHw_REG_DDR_TIMEOUT_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +/****************************************************************************/ +/** +* @brief VPM phase alignment timeout interrupt disable +* +*/ +/****************************************************************************/ +static inline void chipcHw_vpmHwPhaseAlignTimeoutInterruptDisable(void) +{ + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMPhaseCtrl2 &= ~chipcHw_REG_VPM_TIMEOUT_INTR_ENABLE; + REG_LOCAL_IRQ_RESTORE; +} + +#endif /* CHIPC_INLINE_H */ -- GitLab From 638ee2db1916de4da144f0ed6d156181ede20a41 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:06:47 +0100 Subject: [PATCH 0986/1002] ARM: 5657/1: bcmring: add csp chipc block source code add csp chipc block source code Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/csp/chipc/Makefile | 1 + arch/arm/mach-bcmring/csp/chipc/chipcHw.c | 776 ++++++++++++++++++ .../arm/mach-bcmring/csp/chipc/chipcHw_init.c | 293 +++++++ .../mach-bcmring/csp/chipc/chipcHw_reset.c | 124 +++ arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c | 64 ++ 5 files changed, 1258 insertions(+) create mode 100644 arch/arm/mach-bcmring/csp/chipc/Makefile create mode 100644 arch/arm/mach-bcmring/csp/chipc/chipcHw.c create mode 100644 arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c create mode 100644 arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c create mode 100644 arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c diff --git a/arch/arm/mach-bcmring/csp/chipc/Makefile b/arch/arm/mach-bcmring/csp/chipc/Makefile new file mode 100644 index 0000000000000..673952768ee59 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/chipc/Makefile @@ -0,0 +1 @@ +obj-y += chipcHw.o chipcHw_str.o chipcHw_reset.o chipcHw_init.o diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c new file mode 100644 index 0000000000000..b3a61d860c658 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c @@ -0,0 +1,776 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file chipcHw.c +* +* @brief Low level Various CHIP clock controlling routines +* +* @note +* +* These routines provide basic clock controlling functionality only. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/errno.h> +#include <csp/stdint.h> +#include <csp/module.h> + +#include <mach/csp/chipcHw_def.h> +#include <mach/csp/chipcHw_inline.h> + +#include <csp/reg.h> +#include <csp/delay.h> + +/* ---- Private Constants and Types --------------------------------------- */ + +/* VPM alignment algorithm uses this */ +#define MAX_PHASE_ADJUST_COUNT 0xFFFF /* Max number of times allowed to adjust the phase */ +#define MAX_PHASE_ALIGN_ATTEMPTS 10 /* Max number of attempt to align the phase */ + +/* Local definition of clock type */ +#define PLL_CLOCK 1 /* PLL Clock */ +#define NON_PLL_CLOCK 2 /* Divider clock */ + +static int chipcHw_divide(int num, int denom) + __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Set clock fequency for miscellaneous configurable clocks +* +* This function sets clock frequency +* +* @return Configured clock frequency in hertz +* +*/ +/****************************************************************************/ +chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */ + ) { + volatile uint32_t *pPLLReg = (uint32_t *) 0x0; + volatile uint32_t *pClockCtrl = (uint32_t *) 0x0; + volatile uint32_t *pDependentClock = (uint32_t *) 0x0; + uint32_t vcoFreqPll1Hz = 0; /* Effective VCO frequency for PLL1 in Hz */ + uint32_t vcoFreqPll2Hz = 0; /* Effective VCO frequency for PLL2 in Hz */ + uint32_t dependentClockType = 0; + uint32_t vcoHz = 0; + + /* Get VCO frequencies */ + if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) { + uint64_t adjustFreq = 0; + + vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + + /* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */ + adjustFreq = (uint64_t) chipcHw_XTAL_FREQ_Hz * + (uint64_t) chipcHw_REG_PLL_DIVIDER_NDIV_f_SS * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, (chipcHw_REG_PLL_PREDIVIDER_P2 * (uint64_t) chipcHw_REG_PLL_DIVIDER_FRAC)); + vcoFreqPll1Hz += (uint32_t) adjustFreq; + } else { + vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + } + vcoFreqPll2Hz = + chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + + switch (clock) { + case chipcHw_CLOCK_DDR: + pPLLReg = &pChipcHw->DDRClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ARM: + pPLLReg = &pChipcHw->ARMClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ESW: + pPLLReg = &pChipcHw->ESWClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_VPM: + pPLLReg = &pChipcHw->VPMClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ESW125: + pPLLReg = &pChipcHw->ESW125Clock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_UART: + pPLLReg = &pChipcHw->UARTClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SDIO0: + pPLLReg = &pChipcHw->SDIO0Clock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SDIO1: + pPLLReg = &pChipcHw->SDIO1Clock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SPI: + pPLLReg = &pChipcHw->SPIClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ETM: + pPLLReg = &pChipcHw->ETMClock; + vcoHz = vcoFreqPll1Hz; + break; + case chipcHw_CLOCK_USB: + pPLLReg = &pChipcHw->USBClock; + vcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_LCD: + pPLLReg = &pChipcHw->LCDClock; + vcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_APM: + pPLLReg = &pChipcHw->APMClock; + vcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_BUS: + pClockCtrl = &pChipcHw->ACLKClock; + pDependentClock = &pChipcHw->ARMClock; + vcoHz = vcoFreqPll1Hz; + dependentClockType = PLL_CLOCK; + break; + case chipcHw_CLOCK_OTP: + pClockCtrl = &pChipcHw->OTPClock; + break; + case chipcHw_CLOCK_I2C: + pClockCtrl = &pChipcHw->I2CClock; + break; + case chipcHw_CLOCK_I2S0: + pClockCtrl = &pChipcHw->I2S0Clock; + break; + case chipcHw_CLOCK_RTBUS: + pClockCtrl = &pChipcHw->RTBUSClock; + pDependentClock = &pChipcHw->ACLKClock; + dependentClockType = NON_PLL_CLOCK; + break; + case chipcHw_CLOCK_APM100: + pClockCtrl = &pChipcHw->APM100Clock; + pDependentClock = &pChipcHw->APMClock; + vcoHz = vcoFreqPll2Hz; + dependentClockType = PLL_CLOCK; + break; + case chipcHw_CLOCK_TSC: + pClockCtrl = &pChipcHw->TSCClock; + break; + case chipcHw_CLOCK_LED: + pClockCtrl = &pChipcHw->LEDClock; + break; + case chipcHw_CLOCK_I2S1: + pClockCtrl = &pChipcHw->I2S1Clock; + break; + } + + if (pPLLReg) { + /* Obtain PLL clock frequency */ + if (*pPLLReg & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) { + /* Return crystal clock frequency when bypassed */ + return chipcHw_XTAL_FREQ_Hz; + } else if (clock == chipcHw_CLOCK_DDR) { + /* DDR frequency is configured in PLLDivider register */ + return chipcHw_divide (vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256)); + } else { + /* From chip revision number B0, LCD clock is internally divided by 2 */ + if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) { + vcoHz >>= 1; + } + /* Obtain PLL clock frequency using VCO dividers */ + return chipcHw_divide(vcoHz, ((*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256)); + } + } else if (pClockCtrl) { + /* Obtain divider clock frequency */ + uint32_t div; + uint32_t freq = 0; + + if (*pClockCtrl & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) { + /* Return crystal clock frequency when bypassed */ + return chipcHw_XTAL_FREQ_Hz; + } else if (pDependentClock) { + /* Identify the dependent clock frequency */ + switch (dependentClockType) { + case PLL_CLOCK: + if (*pDependentClock & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) { + /* Use crystal clock frequency when dependent PLL clock is bypassed */ + freq = chipcHw_XTAL_FREQ_Hz; + } else { + /* Obtain PLL clock frequency using VCO dividers */ + div = *pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK; + freq = div ? chipcHw_divide(vcoHz, div) : 0; + } + break; + case NON_PLL_CLOCK: + if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) { + freq = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS); + } else { + if (*pDependentClock & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) { + /* Use crystal clock frequency when dependent divider clock is bypassed */ + freq = chipcHw_XTAL_FREQ_Hz; + } else { + /* Obtain divider clock frequency using XTAL dividers */ + div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK; + freq = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, (div ? div : 256)); + } + } + break; + } + } else { + /* Dependent on crystal clock */ + freq = chipcHw_XTAL_FREQ_Hz; + } + + div = *pClockCtrl & chipcHw_REG_DIV_CLOCK_DIV_MASK; + return chipcHw_divide(freq, (div ? div : 256)); + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Set clock fequency for miscellaneous configurable clocks +* +* This function sets clock frequency +* +* @return Configured clock frequency in Hz +* +*/ +/****************************************************************************/ +chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock, /* [ IN ] Configurable clock */ + uint32_t freq /* [ IN ] Clock frequency in Hz */ + ) { + volatile uint32_t *pPLLReg = (uint32_t *) 0x0; + volatile uint32_t *pClockCtrl = (uint32_t *) 0x0; + volatile uint32_t *pDependentClock = (uint32_t *) 0x0; + uint32_t vcoFreqPll1Hz = 0; /* Effective VCO frequency for PLL1 in Hz */ + uint32_t desVcoFreqPll1Hz = 0; /* Desired VCO frequency for PLL1 in Hz */ + uint32_t vcoFreqPll2Hz = 0; /* Effective VCO frequency for PLL2 in Hz */ + uint32_t dependentClockType = 0; + uint32_t vcoHz = 0; + uint32_t desVcoHz = 0; + + /* Get VCO frequencies */ + if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) { + uint64_t adjustFreq = 0; + + vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + + /* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */ + adjustFreq = (uint64_t) chipcHw_XTAL_FREQ_Hz * + (uint64_t) chipcHw_REG_PLL_DIVIDER_NDIV_f_SS * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, (chipcHw_REG_PLL_PREDIVIDER_P2 * (uint64_t) chipcHw_REG_PLL_DIVIDER_FRAC)); + vcoFreqPll1Hz += (uint32_t) adjustFreq; + + /* Desired VCO frequency */ + desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + (((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) + 1); + } else { + vcoFreqPll1Hz = desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz * + chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + } + vcoFreqPll2Hz = chipcHw_XTAL_FREQ_Hz * chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) * + ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >> + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT); + + switch (clock) { + case chipcHw_CLOCK_DDR: + /* Configure the DDR_ctrl:BUS ratio settings */ + { + REG_LOCAL_IRQ_SAVE; + /* Dvide DDR_phy by two to obtain DDR_ctrl clock */ + pChipcHw->DDRClock = (pChipcHw->DDRClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((((freq / 2) / chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1) + << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT); + REG_LOCAL_IRQ_RESTORE; + } + pPLLReg = &pChipcHw->DDRClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ARM: + pPLLReg = &pChipcHw->ARMClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ESW: + pPLLReg = &pChipcHw->ESWClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_VPM: + /* Configure the VPM:BUS ratio settings */ + { + REG_LOCAL_IRQ_SAVE; + pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((chipcHw_divide (freq, chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1) + << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT); + REG_LOCAL_IRQ_RESTORE; + } + pPLLReg = &pChipcHw->VPMClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ESW125: + pPLLReg = &pChipcHw->ESW125Clock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_UART: + pPLLReg = &pChipcHw->UARTClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SDIO0: + pPLLReg = &pChipcHw->SDIO0Clock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SDIO1: + pPLLReg = &pChipcHw->SDIO1Clock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_SPI: + pPLLReg = &pChipcHw->SPIClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_ETM: + pPLLReg = &pChipcHw->ETMClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + break; + case chipcHw_CLOCK_USB: + pPLLReg = &pChipcHw->USBClock; + vcoHz = vcoFreqPll2Hz; + desVcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_LCD: + pPLLReg = &pChipcHw->LCDClock; + vcoHz = vcoFreqPll2Hz; + desVcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_APM: + pPLLReg = &pChipcHw->APMClock; + vcoHz = vcoFreqPll2Hz; + desVcoHz = vcoFreqPll2Hz; + break; + case chipcHw_CLOCK_BUS: + pClockCtrl = &pChipcHw->ACLKClock; + pDependentClock = &pChipcHw->ARMClock; + vcoHz = vcoFreqPll1Hz; + desVcoHz = desVcoFreqPll1Hz; + dependentClockType = PLL_CLOCK; + break; + case chipcHw_CLOCK_OTP: + pClockCtrl = &pChipcHw->OTPClock; + break; + case chipcHw_CLOCK_I2C: + pClockCtrl = &pChipcHw->I2CClock; + break; + case chipcHw_CLOCK_I2S0: + pClockCtrl = &pChipcHw->I2S0Clock; + break; + case chipcHw_CLOCK_RTBUS: + pClockCtrl = &pChipcHw->RTBUSClock; + pDependentClock = &pChipcHw->ACLKClock; + dependentClockType = NON_PLL_CLOCK; + break; + case chipcHw_CLOCK_APM100: + pClockCtrl = &pChipcHw->APM100Clock; + pDependentClock = &pChipcHw->APMClock; + vcoHz = vcoFreqPll2Hz; + desVcoHz = vcoFreqPll2Hz; + dependentClockType = PLL_CLOCK; + break; + case chipcHw_CLOCK_TSC: + pClockCtrl = &pChipcHw->TSCClock; + break; + case chipcHw_CLOCK_LED: + pClockCtrl = &pChipcHw->LEDClock; + break; + case chipcHw_CLOCK_I2S1: + pClockCtrl = &pChipcHw->I2S1Clock; + break; + } + + if (pPLLReg) { + /* Select XTAL as bypass source */ + reg32_modify_and(pPLLReg, ~chipcHw_REG_PLL_CLOCK_SOURCE_GPIO); + reg32_modify_or(pPLLReg, chipcHw_REG_PLL_CLOCK_BYPASS_SELECT); + /* For DDR settings use only the PLL divider clock */ + if (pPLLReg == &pChipcHw->DDRClock) { + /* Set M1DIV for PLL1, which controls the DDR clock */ + reg32_write(&pChipcHw->PLLDivider, (pChipcHw->PLLDivider & 0x00FFFFFF) | ((chipcHw_REG_PLL_DIVIDER_MDIV (desVcoHz, freq)) << 24)); + /* Calculate expected frequency */ + freq = chipcHw_divide(vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256)); + } else { + /* From chip revision number B0, LCD clock is internally divided by 2 */ + if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) { + desVcoHz >>= 1; + vcoHz >>= 1; + } + /* Set MDIV to change the frequency */ + reg32_modify_and(pPLLReg, ~(chipcHw_REG_PLL_CLOCK_MDIV_MASK)); + reg32_modify_or(pPLLReg, chipcHw_REG_PLL_DIVIDER_MDIV(desVcoHz, freq)); + /* Calculate expected frequency */ + freq = chipcHw_divide(vcoHz, ((*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256)); + } + /* Wait for for atleast 200ns as per the protocol to change frequency */ + udelay(1); + /* Do not bypass */ + reg32_modify_and(pPLLReg, ~chipcHw_REG_PLL_CLOCK_BYPASS_SELECT); + /* Return the configured frequency */ + return freq; + } else if (pClockCtrl) { + uint32_t divider = 0; + + /* Divider clock should not be bypassed */ + reg32_modify_and(pClockCtrl, + ~chipcHw_REG_DIV_CLOCK_BYPASS_SELECT); + + /* Identify the clock source */ + if (pDependentClock) { + switch (dependentClockType) { + case PLL_CLOCK: + divider = chipcHw_divide(chipcHw_divide (desVcoHz, (*pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK)), freq); + break; + case NON_PLL_CLOCK: + { + uint32_t sourceClock = 0; + + if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) { + sourceClock = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS); + } else { + uint32_t div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK; + sourceClock = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, ((div) ? div : 256)); + } + divider = chipcHw_divide(sourceClock, freq); + } + break; + } + } else { + divider = chipcHw_divide(chipcHw_XTAL_FREQ_Hz, freq); + } + + if (divider) { + REG_LOCAL_IRQ_SAVE; + /* Set the divider to obtain the required frequency */ + *pClockCtrl = (*pClockCtrl & (~chipcHw_REG_DIV_CLOCK_DIV_MASK)) | (((divider > 256) ? chipcHw_REG_DIV_CLOCK_DIV_256 : divider) & chipcHw_REG_DIV_CLOCK_DIV_MASK); + REG_LOCAL_IRQ_RESTORE; + return freq; + } + } + + return 0; +} + +EXPORT_SYMBOL(chipcHw_setClockFrequency); + +/****************************************************************************/ +/** +* @brief Set VPM clock in sync with BUS clock for Chip Rev #A0 +* +* This function does the phase adjustment between VPM and BUS clock +* +* @return >= 0 : On success (# of adjustment required) +* -1 : On failure +* +*/ +/****************************************************************************/ +static int vpmPhaseAlignA0(void) +{ + uint32_t phaseControl; + uint32_t phaseValue; + uint32_t prevPhaseComp; + int iter = 0; + int adjustCount = 0; + int count = 0; + + for (iter = 0; (iter < MAX_PHASE_ALIGN_ATTEMPTS) && (adjustCount < MAX_PHASE_ADJUST_COUNT); iter++) { + phaseControl = (pChipcHw->VPMClock & chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT; + phaseValue = 0; + prevPhaseComp = 0; + + /* Step 1: Look for falling PH_COMP transition */ + + /* Read the contents of VPM Clock resgister */ + phaseValue = pChipcHw->VPMClock; + do { + /* Store previous value of phase comparator */ + prevPhaseComp = phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP; + /* Change the value of PH_CTRL. */ + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + /* Read the contents of VPM Clock resgister. */ + phaseValue = pChipcHw->VPMClock; + + if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) { + phaseControl = (0x3F & (phaseControl - 1)); + } else { + /* Increment to the Phase count value for next write, if Phase is not stable. */ + phaseControl = (0x3F & (phaseControl + 1)); + } + /* Count number of adjustment made */ + adjustCount++; + } while (((prevPhaseComp == (phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP)) || /* Look for a transition */ + ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) != 0x0)) && /* Look for a falling edge */ + (adjustCount < MAX_PHASE_ADJUST_COUNT) /* Do not exceed the limit while trying */ + ); + + if (adjustCount >= MAX_PHASE_ADJUST_COUNT) { + /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */ + return -1; + } + + /* Step 2: Keep moving forward to make sure falling PH_COMP transition was valid */ + + for (count = 0; (count < 5) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) { + phaseControl = (0x3F & (phaseControl + 1)); + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + phaseValue = pChipcHw->VPMClock; + /* Count number of adjustment made */ + adjustCount++; + } + + if (adjustCount >= MAX_PHASE_ADJUST_COUNT) { + /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */ + return -1; + } + + if (count != 5) { + /* Detected false transition */ + continue; + } + + /* Step 3: Keep moving backward to make sure falling PH_COMP transition was stable */ + + for (count = 0; (count < 3) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) { + phaseControl = (0x3F & (phaseControl - 1)); + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + phaseValue = pChipcHw->VPMClock; + /* Count number of adjustment made */ + adjustCount++; + } + + if (adjustCount >= MAX_PHASE_ADJUST_COUNT) { + /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */ + return -1; + } + + if (count != 3) { + /* Detected noisy transition */ + continue; + } + + /* Step 4: Keep moving backward before the original transition took place. */ + + for (count = 0; (count < 5); count++) { + phaseControl = (0x3F & (phaseControl - 1)); + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + phaseValue = pChipcHw->VPMClock; + /* Count number of adjustment made */ + adjustCount++; + } + + if (adjustCount >= MAX_PHASE_ADJUST_COUNT) { + /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */ + return -1; + } + + if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0) { + /* Detected false transition */ + continue; + } + + /* Step 5: Re discover the valid transition */ + + do { + /* Store previous value of phase comparator */ + prevPhaseComp = phaseValue; + /* Change the value of PH_CTRL. */ + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= + chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + /* Read the contents of VPM Clock resgister. */ + phaseValue = pChipcHw->VPMClock; + + if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) { + phaseControl = (0x3F & (phaseControl - 1)); + } else { + /* Increment to the Phase count value for next write, if Phase is not stable. */ + phaseControl = (0x3F & (phaseControl + 1)); + } + + /* Count number of adjustment made */ + adjustCount++; + } while (((prevPhaseComp == (phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP)) || ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) != 0x0)) && (adjustCount < MAX_PHASE_ADJUST_COUNT)); + + if (adjustCount >= MAX_PHASE_ADJUST_COUNT) { + /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */ + return -1; + } else { + /* Valid phase must have detected */ + break; + } + } + + /* For VPM Phase should be perfectly aligned. */ + phaseControl = (((pChipcHw->VPMClock >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT) - 1) & 0x3F); + { + REG_LOCAL_IRQ_SAVE; + + pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT); + /* Load new phase value */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + + REG_LOCAL_IRQ_RESTORE; + } + /* Return the status */ + return (int)adjustCount; +} + +/****************************************************************************/ +/** +* @brief Set VPM clock in sync with BUS clock +* +* This function does the phase adjustment between VPM and BUS clock +* +* @return >= 0 : On success (# of adjustment required) +* -1 : On failure +* +*/ +/****************************************************************************/ +int chipcHw_vpmPhaseAlign(void) +{ + + if (chipcHw_getChipRevisionNumber() == chipcHw_REV_NUMBER_A0) { + return vpmPhaseAlignA0(); + } else { + uint32_t phaseControl = chipcHw_getVpmPhaseControl(); + uint32_t phaseValue = 0; + int adjustCount = 0; + + /* Disable VPM access */ + pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE; + /* Disable HW VPM phase alignment */ + chipcHw_vpmHwPhaseAlignDisable(); + /* Enable SW VPM phase alignment */ + chipcHw_vpmSwPhaseAlignEnable(); + /* Adjust VPM phase */ + while (adjustCount < MAX_PHASE_ADJUST_COUNT) { + phaseValue = chipcHw_getVpmHwPhaseAlignStatus(); + + /* Adjust phase control value */ + if (phaseValue > 0xF) { + /* Increment phase control value */ + phaseControl++; + } else if (phaseValue < 0xF) { + /* Decrement phase control value */ + phaseControl--; + } else { + /* Enable VPM access */ + pChipcHw->Spare1 |= chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE; + /* Return adjust count */ + return adjustCount; + } + /* Change the value of PH_CTRL. */ + reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT)); + /* Wait atleast 20 ns */ + udelay(1); + /* Toggle the LOAD_CH after phase control is written. */ + pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE; + /* Count adjustment */ + adjustCount++; + } + } + + /* Disable VPM access */ + pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE; + return -1; +} + +/****************************************************************************/ +/** +* @brief Local Divide function +* +* This function does the divide +* +* @return divide value +* +*/ +/****************************************************************************/ +static int chipcHw_divide(int num, int denom) +{ + int r; + int t = 1; + + /* Shift denom and t up to the largest value to optimize algorithm */ + /* t contains the units of each divide */ + while ((denom & 0x40000000) == 0) { /* fails if denom=0 */ + denom = denom << 1; + t = t << 1; + } + + /* Intialize the result */ + r = 0; + + do { + /* Determine if there exists a positive remainder */ + if ((num - denom) >= 0) { + /* Accumlate t to the result and calculate a new remainder */ + num = num - denom; + r = r + t; + } + /* Continue to shift denom and shift t down to 0 */ + denom = denom >> 1; + t = t >> 1; + } while (t != 0); + + return r; +} diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c new file mode 100644 index 0000000000000..367df75d4bb33 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c @@ -0,0 +1,293 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file chipcHw_init.c +* +* @brief Low level CHIPC PLL configuration functions +* +* @note +* +* These routines provide basic PLL controlling functionality only. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/errno.h> +#include <csp/stdint.h> +#include <csp/module.h> + +#include <mach/csp/chipcHw_def.h> +#include <mach/csp/chipcHw_inline.h> + +#include <csp/reg.h> +#include <csp/delay.h> +/* ---- Private Constants and Types --------------------------------------- */ + +/* + Calculation for NDIV_i to obtain VCO frequency + ----------------------------------------------- + + Freq_vco = Freq_ref * (P2 / P1) * (PLL_NDIV_i + PLL_NDIV_f) + for Freq_vco = VCO_FREQ_MHz + Freq_ref = chipcHw_XTAL_FREQ_Hz + PLL_P1 = PLL_P2 = 1 + and + PLL_NDIV_f = 0 + + We get: + PLL_NDIV_i = Freq_vco / Freq_ref = VCO_FREQ_MHz / chipcHw_XTAL_FREQ_Hz + + Calculation for PLL MDIV to obtain frequency Freq_x for channel x + ----------------------------------------------------------------- + Freq_x = chipcHw_XTAL_FREQ_Hz * PLL_NDIV_i / PLL_MDIV_x = VCO_FREQ_MHz / PLL_MDIV_x + + PLL_MDIV_x = VCO_FREQ_MHz / Freq_x +*/ + +/* ---- Private Variables ------------------------------------------------- */ +/****************************************************************************/ +/** +* @brief Initializes the PLL2 +* +* This function initializes the PLL2 +* +*/ +/****************************************************************************/ +void chipcHw_pll2Enable(uint32_t vcoFreqHz) +{ + uint32_t pllPreDivider2 = 0; + + { + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig2 = + chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET; + + pllPreDivider2 = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN | + chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER | + (chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) << + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P1 << + chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P2 << + chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT); + + /* Enable CHIPC registers to control the PLL */ + pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE; + + /* Set pre divider to get desired VCO frequency */ + pChipcHw->PLLPreDivider2 = pllPreDivider2; + /* Set NDIV Frac */ + pChipcHw->PLLDivider2 = chipcHw_REG_PLL_DIVIDER_NDIV_f; + + /* This has to be removed once the default values are fixed for PLL2. */ + pChipcHw->PLLControl12 = 0x38000700; + pChipcHw->PLLControl22 = 0x00000015; + + /* Reset PLL2 */ + if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) { + pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_VCO_1601_3200 | + chipcHw_REG_PLL_CONFIG_POWER_DOWN; + } else { + pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_VCO_800_1600 | + chipcHw_REG_PLL_CONFIG_POWER_DOWN; + } + REG_LOCAL_IRQ_RESTORE; + } + + /* Insert certain amount of delay before deasserting ARESET. */ + udelay(1); + + { + REG_LOCAL_IRQ_SAVE; + /* Remove analog reset and Power on the PLL */ + pChipcHw->PLLConfig2 &= + ~(chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_POWER_DOWN); + + REG_LOCAL_IRQ_RESTORE; + + } + + /* Wait until PLL is locked */ + while (!(pChipcHw->PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED)) + ; + + { + REG_LOCAL_IRQ_SAVE; + /* Remove digital reset */ + pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_D_RESET; + + REG_LOCAL_IRQ_RESTORE; + } +} + +EXPORT_SYMBOL(chipcHw_pll2Enable); + +/****************************************************************************/ +/** +* @brief Initializes the PLL1 +* +* This function initializes the PLL1 +* +*/ +/****************************************************************************/ +void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport) +{ + uint32_t pllPreDivider = 0; + + { + REG_LOCAL_IRQ_SAVE; + + pChipcHw->PLLConfig = + chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET; + /* Setting VCO frequency */ + if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) { + pllPreDivider = + chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_1_8 | + ((chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) - + 1) << chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P1 << + chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P2 << + chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT); + } else { + pllPreDivider = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN | + chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER | + (chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) << + chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P1 << + chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) | + (chipcHw_REG_PLL_PREDIVIDER_P2 << + chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT); + } + + /* Enable CHIPC registers to control the PLL */ + pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE; + + /* Set pre divider to get desired VCO frequency */ + pChipcHw->PLLPreDivider = pllPreDivider; + /* Set NDIV Frac */ + if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) { + pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV | + chipcHw_REG_PLL_DIVIDER_NDIV_f_SS; + } else { + pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV | + chipcHw_REG_PLL_DIVIDER_NDIV_f; + } + + /* Reset PLL1 */ + if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) { + pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_VCO_1601_3200 | + chipcHw_REG_PLL_CONFIG_POWER_DOWN; + } else { + pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET | + chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_VCO_800_1600 | + chipcHw_REG_PLL_CONFIG_POWER_DOWN; + } + + REG_LOCAL_IRQ_RESTORE; + + /* Insert certain amount of delay before deasserting ARESET. */ + udelay(1); + + { + REG_LOCAL_IRQ_SAVE; + /* Remove analog reset and Power on the PLL */ + pChipcHw->PLLConfig &= + ~(chipcHw_REG_PLL_CONFIG_A_RESET | + chipcHw_REG_PLL_CONFIG_POWER_DOWN); + REG_LOCAL_IRQ_RESTORE; + } + + /* Wait until PLL is locked */ + while (!(pChipcHw->PLLStatus & chipcHw_REG_PLL_STATUS_LOCKED) + || !(pChipcHw-> + PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED)) + ; + + /* Remove digital reset */ + { + REG_LOCAL_IRQ_SAVE; + pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_D_RESET; + REG_LOCAL_IRQ_RESTORE; + } + } +} + +EXPORT_SYMBOL(chipcHw_pll1Enable); + +/****************************************************************************/ +/** +* @brief Initializes the chipc module +* +* This function initializes the PLLs and core system clocks +* +*/ +/****************************************************************************/ + +void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam /* [ IN ] Misc chip initialization parameter */ + ) { +#if !(defined(__KERNEL__) && !defined(STANDALONE)) + delay_init(); +#endif + + /* Do not program PLL, when warm reset */ + if (!(chipcHw_getStickyBits() & chipcHw_REG_STICKY_CHIP_WARM_RESET)) { + chipcHw_pll1Enable(initParam->pllVcoFreqHz, + initParam->ssSupport); + chipcHw_pll2Enable(initParam->pll2VcoFreqHz); + } else { + /* Clear sticky bits */ + chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_WARM_RESET); + } + /* Clear sticky bits */ + chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_SOFT_RESET); + + /* Before configuring the ARM clock, atleast we need to make sure BUS clock maintains the proper ratio with ARM clock */ + pChipcHw->ACLKClock = + (pChipcHw-> + ACLKClock & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam-> + armBusRatio & + chipcHw_REG_ACLKClock_CLK_DIV_MASK); + + /* Set various core component frequencies. The order in which this is done is important for some. */ + /* The RTBUS (DDR PHY) is derived from the BUS, and the BUS from the ARM, and VPM needs to know BUS */ + /* frequency to find its ratio with the BUS. Hence we must set the ARM first, followed by the BUS, */ + /* then VPM and RTBUS. */ + + chipcHw_setClockFrequency(chipcHw_CLOCK_ARM, + initParam->busClockFreqHz * + initParam->armBusRatio); + chipcHw_setClockFrequency(chipcHw_CLOCK_BUS, initParam->busClockFreqHz); + chipcHw_setClockFrequency(chipcHw_CLOCK_VPM, + initParam->busClockFreqHz * + initParam->vpmBusRatio); + chipcHw_setClockFrequency(chipcHw_CLOCK_DDR, + initParam->busClockFreqHz * + initParam->ddrBusRatio); + chipcHw_setClockFrequency(chipcHw_CLOCK_RTBUS, + initParam->busClockFreqHz / 2); +} diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c new file mode 100644 index 0000000000000..2671d8896bbb5 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c @@ -0,0 +1,124 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ +#include <csp/stdint.h> +#include <mach/csp/chipcHw_def.h> +#include <mach/csp/chipcHw_inline.h> +#include <csp/intcHw.h> +#include <csp/cache.h> + +/* ---- Private Constants and Types --------------------------------------- */ +/* ---- Private Variables ------------------------------------------------- */ +void chipcHw_reset_run_from_aram(void); + +typedef void (*RUNFUNC) (void); + +/****************************************************************************/ +/** +* @brief warmReset +* +* @note warmReset configures the clocks which are not reset back to the state +* required to execute on reset. To do so we need to copy the code into internal +* memory to change the ARM clock while we are not executing from DDR. +*/ +/****************************************************************************/ +void chipcHw_reset(uint32_t mask) +{ + int i = 0; + RUNFUNC runFunc = (RUNFUNC) (unsigned long)MM_ADDR_IO_ARAM; + + /* Disable all interrupts */ + intcHw_irq_disable(INTCHW_INTC0, 0xffffffff); + intcHw_irq_disable(INTCHW_INTC1, 0xffffffff); + intcHw_irq_disable(INTCHW_SINTC, 0xffffffff); + + { + REG_LOCAL_IRQ_SAVE; + if (mask & chipcHw_REG_SOFT_RESET_CHIP_SOFT) { + chipcHw_softReset(chipcHw_REG_SOFT_RESET_CHIP_SOFT); + } + /* Bypass the PLL clocks before reboot */ + pChipcHw->UARTClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT; + pChipcHw->SPIClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT; + + /* Copy the chipcHw_warmReset_run_from_aram function into ARAM */ + do { + ((uint32_t *) MM_IO_BASE_ARAM)[i] = + ((uint32_t *) &chipcHw_reset_run_from_aram)[i]; + i++; + } while (((uint32_t *) MM_IO_BASE_ARAM)[i - 1] != 0xe1a0f00f); /* 0xe1a0f00f == asm ("mov r15, r15"); */ + + CSP_CACHE_FLUSH_ALL; + + /* run the function from ARAM */ + runFunc(); + + /* Code will never get here, but include it to balance REG_LOCAL_IRQ_SAVE above */ + REG_LOCAL_IRQ_RESTORE; + } +} + +/* This function must run from internal memory */ +void chipcHw_reset_run_from_aram(void) +{ +/* Make sure, pipeline is filled with instructions coming from ARAM */ +__asm (" nop \n\t" + " nop \n\t" +#if defined(__KERNEL__) && !defined(STANDALONE) + " MRC p15,#0x0,r0,c1,c0,#0 \n\t" + " BIC r0,r0,#0xd \n\t" + " MCR p15,#0x0,r0,c1,c0,#0 \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" +#endif + " nop \n\t" + " nop \n\t" +/* Bypass the ARM clock and switch to XTAL clock */ + " MOV r2,#0x80000000 \n\t" + " LDR r3,[r2,#8] \n\t" + " ORR r3,r3,#0x20000 \n\t" + " STR r3,[r2,#8] \n\t" + + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" + " nop \n\t" +/* Issue reset */ + " MOV r3,#0x2 \n\t" + " STR r3,[r2,#0x80] \n\t" +/* End here */ + " MOV pc,pc \n\t"); +/* 0xe1a0f00f == asm ("mov r15, r15"); */ +} diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c new file mode 100644 index 0000000000000..54ad964fe94ca --- /dev/null +++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c @@ -0,0 +1,64 @@ +/***************************************************************************** +* Copyright 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ +/****************************************************************************/ +/** +* @file chipcHw_str.c +* +* @brief Contains strings which are useful to linux and csp +* +* @note +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <mach/csp/chipcHw_inline.h> + +/* ---- Private Constants and Types --------------------------------------- */ + +static const char *gMuxStr[] = { + "GPIO", /* 0 */ + "KeyPad", /* 1 */ + "I2C-Host", /* 2 */ + "SPI", /* 3 */ + "Uart", /* 4 */ + "LED-Mtx-P", /* 5 */ + "LED-Mtx-S", /* 6 */ + "SDIO-0", /* 7 */ + "SDIO-1", /* 8 */ + "PCM", /* 9 */ + "I2S", /* 10 */ + "ETM", /* 11 */ + "Debug", /* 12 */ + "Misc", /* 13 */ + "0xE", /* 14 */ + "0xF", /* 15 */ +}; + +/****************************************************************************/ +/** +* @brief Retrieves a string representation of the mux setting for a pin. +* +* @return Pointer to a character string. +*/ +/****************************************************************************/ + +const char *chipcHw_getGpioPinFunctionStr(int pin) +{ + if ((pin < 0) || (pin >= chipcHw_GPIO_COUNT)) { + return ""; + } + + return gMuxStr[chipcHw_getGpioPinFunction(pin)]; +} -- GitLab From 1a4a561bdd838b4455d57edf0deaf83e894d795e Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:07:22 +0100 Subject: [PATCH 0987/1002] ARM: 5658/1: bcmring: add csp dmac header files add csp dmac header files Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/csp/dmacHw.h | 596 ++++++++++++++++++ .../include/mach/csp/dmacHw_priv.h | 145 +++++ .../include/mach/csp/dmacHw_reg.h | 406 ++++++++++++ 3 files changed, 1147 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/csp/dmacHw.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h diff --git a/arch/arm/mach-bcmring/include/csp/dmacHw.h b/arch/arm/mach-bcmring/include/csp/dmacHw.h new file mode 100644 index 0000000000000..5d510130a25f9 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/dmacHw.h @@ -0,0 +1,596 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dmacHw.h +* +* @brief API definitions for low level DMA controller driver +* +*/ +/****************************************************************************/ +#ifndef _DMACHW_H +#define _DMACHW_H + +#include <stddef.h> + +#include <csp/stdint.h> +#include <mach/csp/dmacHw_reg.h> + +/* Define DMA Channel ID using DMA controller number (m) and channel number (c). + + System specific channel ID should be defined as follows + + For example: + + #include <dmacHw.h> + ... + #define systemHw_LCD_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,5) + #define systemHw_SWITCH_RX_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,0) + #define systemHw_SWITCH_TX_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,1) + #define systemHw_APM_RX_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,3) + #define systemHw_APM_TX_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,4) + ... + #define systemHw_SHARED1_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(1,4) + #define systemHw_SHARED2_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(1,5) + #define systemHw_SHARED3_CHANNEL_ID dmacHw_MAKE_CHANNEL_ID(0,6) + ... +*/ +#define dmacHw_MAKE_CHANNEL_ID(m, c) (m << 8 | c) + +typedef enum { + dmacHw_CHANNEL_PRIORITY_0 = dmacHw_REG_CFG_LO_CH_PRIORITY_0, /* Channel priority 0. Lowest priority DMA channel */ + dmacHw_CHANNEL_PRIORITY_1 = dmacHw_REG_CFG_LO_CH_PRIORITY_1, /* Channel priority 1 */ + dmacHw_CHANNEL_PRIORITY_2 = dmacHw_REG_CFG_LO_CH_PRIORITY_2, /* Channel priority 2 */ + dmacHw_CHANNEL_PRIORITY_3 = dmacHw_REG_CFG_LO_CH_PRIORITY_3, /* Channel priority 3 */ + dmacHw_CHANNEL_PRIORITY_4 = dmacHw_REG_CFG_LO_CH_PRIORITY_4, /* Channel priority 4 */ + dmacHw_CHANNEL_PRIORITY_5 = dmacHw_REG_CFG_LO_CH_PRIORITY_5, /* Channel priority 5 */ + dmacHw_CHANNEL_PRIORITY_6 = dmacHw_REG_CFG_LO_CH_PRIORITY_6, /* Channel priority 6 */ + dmacHw_CHANNEL_PRIORITY_7 = dmacHw_REG_CFG_LO_CH_PRIORITY_7 /* Channel priority 7. Highest priority DMA channel */ +} dmacHw_CHANNEL_PRIORITY_e; + +/* Source destination master interface */ +typedef enum { + dmacHw_SRC_MASTER_INTERFACE_1 = dmacHw_REG_CTL_SMS_1, /* Source DMA master interface 1 */ + dmacHw_SRC_MASTER_INTERFACE_2 = dmacHw_REG_CTL_SMS_2, /* Source DMA master interface 2 */ + dmacHw_DST_MASTER_INTERFACE_1 = dmacHw_REG_CTL_DMS_1, /* Destination DMA master interface 1 */ + dmacHw_DST_MASTER_INTERFACE_2 = dmacHw_REG_CTL_DMS_2 /* Destination DMA master interface 2 */ +} dmacHw_MASTER_INTERFACE_e; + +typedef enum { + dmacHw_SRC_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_SRC_TR_WIDTH_8, /* Source 8 bit (1 byte) per transaction */ + dmacHw_SRC_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_SRC_TR_WIDTH_16, /* Source 16 bit (2 byte) per transaction */ + dmacHw_SRC_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_SRC_TR_WIDTH_32, /* Source 32 bit (4 byte) per transaction */ + dmacHw_SRC_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_SRC_TR_WIDTH_64, /* Source 64 bit (8 byte) per transaction */ + dmacHw_DST_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_DST_TR_WIDTH_8, /* Destination 8 bit (1 byte) per transaction */ + dmacHw_DST_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_DST_TR_WIDTH_16, /* Destination 16 bit (2 byte) per transaction */ + dmacHw_DST_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_DST_TR_WIDTH_32, /* Destination 32 bit (4 byte) per transaction */ + dmacHw_DST_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_DST_TR_WIDTH_64 /* Destination 64 bit (8 byte) per transaction */ +} dmacHw_TRANSACTION_WIDTH_e; + +typedef enum { + dmacHw_SRC_BURST_WIDTH_0 = dmacHw_REG_CTL_SRC_MSIZE_0, /* Source No burst */ + dmacHw_SRC_BURST_WIDTH_4 = dmacHw_REG_CTL_SRC_MSIZE_4, /* Source 4 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ + dmacHw_SRC_BURST_WIDTH_8 = dmacHw_REG_CTL_SRC_MSIZE_8, /* Source 8 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ + dmacHw_SRC_BURST_WIDTH_16 = dmacHw_REG_CTL_SRC_MSIZE_16, /* Source 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ + dmacHw_DST_BURST_WIDTH_0 = dmacHw_REG_CTL_DST_MSIZE_0, /* Destination No burst */ + dmacHw_DST_BURST_WIDTH_4 = dmacHw_REG_CTL_DST_MSIZE_4, /* Destination 4 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ + dmacHw_DST_BURST_WIDTH_8 = dmacHw_REG_CTL_DST_MSIZE_8, /* Destination 8 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ + dmacHw_DST_BURST_WIDTH_16 = dmacHw_REG_CTL_DST_MSIZE_16 /* Destination 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */ +} dmacHw_BURST_WIDTH_e; + +typedef enum { + dmacHw_TRANSFER_TYPE_MEM_TO_MEM = dmacHw_REG_CTL_TTFC_MM_DMAC, /* Memory to memory transfer */ + dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM = dmacHw_REG_CTL_TTFC_PM_DMAC, /* Peripheral to memory transfer */ + dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_MP_DMAC, /* Memory to peripheral transfer */ + dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_PP_DMAC /* Peripheral to peripheral transfer */ +} dmacHw_TRANSFER_TYPE_e; + +typedef enum { + dmacHw_TRANSFER_MODE_PERREQUEST, /* Block transfer per DMA request */ + dmacHw_TRANSFER_MODE_CONTINUOUS, /* Continuous transfer of streaming data */ + dmacHw_TRANSFER_MODE_PERIODIC /* Periodic transfer of streaming data */ +} dmacHw_TRANSFER_MODE_e; + +typedef enum { + dmacHw_SRC_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_SINC_INC, /* Increment source address after every transaction */ + dmacHw_SRC_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_SINC_DEC, /* Decrement source address after every transaction */ + dmacHw_DST_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_DINC_INC, /* Increment destination address after every transaction */ + dmacHw_DST_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_DINC_DEC, /* Decrement destination address after every transaction */ + dmacHw_SRC_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_SINC_NC, /* No change in source address after every transaction */ + dmacHw_DST_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_DINC_NC /* No change in destination address after every transaction */ +} dmacHw_ADDRESS_UPDATE_MODE_e; + +typedef enum { + dmacHw_FLOW_CONTROL_DMA, /* DMA working as flow controller (default) */ + dmacHw_FLOW_CONTROL_PERIPHERAL /* Peripheral working as flow controller */ +} dmacHw_FLOW_CONTROL_e; + +typedef enum { + dmacHw_TRANSFER_STATUS_BUSY, /* DMA Transfer ongoing */ + dmacHw_TRANSFER_STATUS_DONE, /* DMA Transfer completed */ + dmacHw_TRANSFER_STATUS_ERROR /* DMA Transfer error */ +} dmacHw_TRANSFER_STATUS_e; + +typedef enum { + dmacHw_INTERRUPT_DISABLE, /* Interrupt disable */ + dmacHw_INTERRUPT_ENABLE /* Interrupt enable */ +} dmacHw_INTERRUPT_e; + +typedef enum { + dmacHw_INTERRUPT_STATUS_NONE = 0x0, /* No DMA interrupt */ + dmacHw_INTERRUPT_STATUS_TRANS = 0x1, /* End of DMA transfer interrupt */ + dmacHw_INTERRUPT_STATUS_BLOCK = 0x2, /* End of block transfer interrupt */ + dmacHw_INTERRUPT_STATUS_ERROR = 0x4 /* Error interrupt */ +} dmacHw_INTERRUPT_STATUS_e; + +typedef enum { + dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM, /* Number of DMA channel */ + dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE, /* Maximum channel burst size */ + dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM, /* Number of DMA master interface */ + dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH, /* Channel Data bus width */ + dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE /* Channel FIFO size */ +} dmacHw_CONTROLLER_ATTRIB_e; + +typedef unsigned long dmacHw_HANDLE_t; /* DMA channel handle */ +typedef uint32_t dmacHw_ID_t; /* DMA channel Id. Must be created using + "dmacHw_MAKE_CHANNEL_ID" macro + */ +/* DMA channel configuration parameters */ +typedef struct { + uint32_t srcPeripheralPort; /* Source peripheral port */ + uint32_t dstPeripheralPort; /* Destination peripheral port */ + uint32_t srcStatusRegisterAddress; /* Source status register address */ + uint32_t dstStatusRegisterAddress; /* Destination status register address of type */ + + uint32_t srcGatherWidth; /* Number of bytes gathered before successive gather opearation */ + uint32_t srcGatherJump; /* Number of bytes jumpped before successive gather opearation */ + uint32_t dstScatterWidth; /* Number of bytes sacattered before successive scatter opearation */ + uint32_t dstScatterJump; /* Number of bytes jumpped before successive scatter opearation */ + uint32_t maxDataPerBlock; /* Maximum number of bytes to be transferred per block/descrptor. + 0 = Maximum possible. + */ + + dmacHw_ADDRESS_UPDATE_MODE_e srcUpdate; /* Source address update mode */ + dmacHw_ADDRESS_UPDATE_MODE_e dstUpdate; /* Destination address update mode */ + dmacHw_TRANSFER_TYPE_e transferType; /* DMA transfer type */ + dmacHw_TRANSFER_MODE_e transferMode; /* DMA transfer mode */ + dmacHw_MASTER_INTERFACE_e srcMasterInterface; /* DMA source interface */ + dmacHw_MASTER_INTERFACE_e dstMasterInterface; /* DMA destination interface */ + dmacHw_TRANSACTION_WIDTH_e srcMaxTransactionWidth; /* Source transaction width */ + dmacHw_TRANSACTION_WIDTH_e dstMaxTransactionWidth; /* Destination transaction width */ + dmacHw_BURST_WIDTH_e srcMaxBurstWidth; /* Source burst width */ + dmacHw_BURST_WIDTH_e dstMaxBurstWidth; /* Destination burst width */ + dmacHw_INTERRUPT_e blockTransferInterrupt; /* Block trsnafer interrupt */ + dmacHw_INTERRUPT_e completeTransferInterrupt; /* Complete DMA trsnafer interrupt */ + dmacHw_INTERRUPT_e errorInterrupt; /* Error interrupt */ + dmacHw_CHANNEL_PRIORITY_e channelPriority; /* Channel priority */ + dmacHw_FLOW_CONTROL_e flowControler; /* Data flow controller */ +} dmacHw_CONFIG_t; + +/****************************************************************************/ +/** +* @brief Initializes DMA +* +* This function initializes DMA CSP driver +* +* @note +* Must be called before using any DMA channel +*/ +/****************************************************************************/ +void dmacHw_initDma(void); + +/****************************************************************************/ +/** +* @brief Exit function for DMA +* +* This function isolates DMA from the system +* +*/ +/****************************************************************************/ +void dmacHw_exitDma(void); + +/****************************************************************************/ +/** +* @brief Gets a handle to a DMA channel +* +* This function returns a handle, representing a control block of a particular DMA channel +* +* @return -1 - On Failure +* handle - On Success, representing a channel control block +* +* @note +* None Channel ID must be created using "dmacHw_MAKE_CHANNEL_ID" macro +*/ +/****************************************************************************/ +dmacHw_HANDLE_t dmacHw_getChannelHandle(dmacHw_ID_t channelId /* [ IN ] DMA Channel Id */ + ); + +/****************************************************************************/ +/** +* @brief Initializes a DMA channel for use +* +* This function initializes and resets a DMA channel for use +* +* @return -1 - On Failure +* 0 - On Success +* +* @note +* None +*/ +/****************************************************************************/ +int dmacHw_initChannel(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Estimates number of descriptor needed to perform certain DMA transfer +* +* +* @return On failure : -1 +* On success : Number of descriptor count +* +* +*/ +/****************************************************************************/ +int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pSrcAddr, /* [ IN ] Source (Peripheral/Memory) address */ + void *pDstAddr, /* [ IN ] Destination (Peripheral/Memory) address */ + size_t dataLen /* [ IN ] Data length in bytes */ + ); + +/****************************************************************************/ +/** +* @brief Initializes descriptor ring +* +* This function will initializes the descriptor ring of a DMA channel +* +* +* @return -1 - On failure +* 0 - On success +* @note +* - "len" parameter should be obtained from "dmacHw_descriptorLen" +* - Descriptor buffer MUST be 32 bit aligned and uncached as it +* is accessed by ARM and DMA +*/ +/****************************************************************************/ +int dmacHw_initDescriptor(void *pDescriptorVirt, /* [ IN ] Virtual address of uncahced buffer allocated to form descriptor ring */ + uint32_t descriptorPhyAddr, /* [ IN ] Physical address of pDescriptorVirt (descriptor buffer) */ + uint32_t len, /* [ IN ] Size of the pBuf */ + uint32_t num /* [ IN ] Number of descriptor in the ring */ + ); + +/****************************************************************************/ +/** +* @brief Finds amount of memory required to form a descriptor ring +* +* +* @return Number of bytes required to form a descriptor ring +* +* +* @note +* None +*/ +/****************************************************************************/ +uint32_t dmacHw_descriptorLen(uint32_t descCnt /* [ IN ] Number of descriptor in the ring */ + ); + +/****************************************************************************/ +/** +* @brief Configure DMA channel +* +* @return 0 : On success +* -1 : On failure +*/ +/****************************************************************************/ +int dmacHw_configChannel(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig /* [ IN ] Configuration settings */ + ); + +/****************************************************************************/ +/** +* @brief Set descriptors for known data length +* +* When DMA has to work as a flow controller, this function prepares the +* descriptor chain to transfer data +* +* from: +* - Memory to memory +* - Peripheral to memory +* - Memory to Peripheral +* - Peripheral to Peripheral +* +* @return -1 - On failure +* 0 - On success +* +*/ +/****************************************************************************/ +int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void *pSrcAddr, /* [ IN ] Source (Peripheral/Memory) address */ + void *pDstAddr, /* [ IN ] Destination (Peripheral/Memory) address */ + size_t dataLen /* [ IN ] Length in bytes */ + ); + +/****************************************************************************/ +/** +* @brief Indicates whether DMA transfer is in progress or completed +* +* @return DMA transfer status +* dmacHw_TRANSFER_STATUS_BUSY: DMA Transfer ongoing +* dmacHw_TRANSFER_STATUS_DONE: DMA Transfer completed +* dmacHw_TRANSFER_STATUS_ERROR: DMA Transfer error +* +*/ +/****************************************************************************/ +dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Set descriptor carrying control information +* +* This function will be used to send specific control information to the device +* using the DMA channel +* +* +* @return -1 - On failure +* 0 - On success +* +* @note +* None +*/ +/****************************************************************************/ +int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + uint32_t ctlAddress, /* [ IN ] Address of the device control register */ + uint32_t control /* [ IN ] Device control information */ + ); + +/****************************************************************************/ +/** +* @brief Read data DMA transferred to memory +* +* This function will read data that has been DMAed to memory while transfering from: +* - Memory to memory +* - Peripheral to memory +* +* @return 0 - No more data is available to read +* 1 - More data might be available to read +* +*/ +/****************************************************************************/ +int dmacHw_readTransferredData(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void **ppBbuf, /* [ OUT ] Data received */ + size_t *pLlen /* [ OUT ] Length of the data received */ + ); + +/****************************************************************************/ +/** +* @brief Prepares descriptor ring, when source peripheral working as a flow controller +* +* This function will form the descriptor ring by allocating buffers, when source peripheral +* has to work as a flow controller to transfer data from: +* - Peripheral to memory. +* +* @return -1 - On failure +* 0 - On success +* +* +* @note +* None +*/ +/****************************************************************************/ +int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + uint32_t srcAddr, /* [ IN ] Source peripheral address */ + void *(*fpAlloc) (int len), /* [ IN ] Function pointer that provides destination memory */ + int len, /* [ IN ] Number of bytes "fpAlloc" will allocate for destination */ + int num /* [ IN ] Number of descriptor to set */ + ); + +/****************************************************************************/ +/** +* @brief Program channel register to initiate transfer +* +* @return void +* +* +* @note +* - Descriptor buffer MUST ALWAYS be flushed before calling this function +* - This function should also be called from ISR to program the channel with +* pending descriptors +*/ +/****************************************************************************/ +void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor /* [ IN ] Descriptor buffer */ + ); + +/****************************************************************************/ +/** +* @brief Resets descriptor control information +* +* @return void +*/ +/****************************************************************************/ +void dmacHw_resetDescriptorControl(void *pDescriptor /* [ IN ] Descriptor buffer */ + ); + +/****************************************************************************/ +/** +* @brief Program channel register to stop transfer +* +* Ensures the channel is not doing any transfer after calling this function +* +* @return void +* +*/ +/****************************************************************************/ +void dmacHw_stopTransfer(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Check the existance of pending descriptor +* +* This function confirmes if there is any pending descriptor in the chain +* to program the channel +* +* @return 1 : Channel need to be programmed with pending descriptor +* 0 : No more pending descriptor to programe the channel +* +* @note +* - This function should be called from ISR in case there are pending +* descriptor to program the channel. +* +* Example: +* +* dmac_isr () +* { +* ... +* if (dmacHw_descriptorPending (handle)) +* { +* dmacHw_initiateTransfer (handle); +* } +* } +* +*/ +/****************************************************************************/ +uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *pDescriptor /* [ IN ] Descriptor buffer */ + ); + +/****************************************************************************/ +/** +* @brief Deallocates source or destination memory, allocated +* +* This function can be called to deallocate data memory that was DMAed successfully +* +* @return -1 - On failure +* 0 - On success +* +* @note +* This function will be called ONLY, when source OR destination address is pointing +* to dynamic memory +*/ +/****************************************************************************/ +int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void (*fpFree) (void *) /* [ IN ] Function pointer to free data memory */ + ); + +/****************************************************************************/ +/** +* @brief Clears the interrupt +* +* This function clears the DMA channel specific interrupt +* +* @return N/A +* +* @note +* Must be called under the context of ISR +*/ +/****************************************************************************/ +void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Returns the cause of channel specific DMA interrupt +* +* This function returns the cause of interrupt +* +* @return Interrupt status, each bit representing a specific type of interrupt +* of type dmacHw_INTERRUPT_STATUS_e +* @note +* This function should be called under the context of ISR +*/ +/****************************************************************************/ +dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Indentifies a DMA channel causing interrupt +* +* This functions returns a channel causing interrupt of type dmacHw_INTERRUPT_STATUS_e +* +* @return NULL : No channel causing DMA interrupt +* ! NULL : Handle to a channel causing DMA interrupt +* @note +* dmacHw_clearInterrupt() must be called with a valid handle after calling this function +*/ +/****************************************************************************/ +dmacHw_HANDLE_t dmacHw_getInterruptSource(void); + +/****************************************************************************/ +/** +* @brief Sets channel specific user data +* +* This function associates user data to a specif DMA channel +* +*/ +/****************************************************************************/ +void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *userData /* [ IN ] User data */ + ); + +/****************************************************************************/ +/** +* @brief Gets channel specific user data +* +* This function returns user data specific to a DMA channel +* +* @return user data +*/ +/****************************************************************************/ +void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ); + +/****************************************************************************/ +/** +* @brief Displays channel specific registers and other control parameters +* +* +* @return void +* +* @note +* None +*/ +/****************************************************************************/ +void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */ + ); + +/****************************************************************************/ +/** +* @brief Provides DMA controller attributes +* +* +* @return DMA controller attributes +* +* @note +* None +*/ +/****************************************************************************/ +uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONTROLLER_ATTRIB_e attr /* [ IN ] DMA Controler attribute of type dmacHw_CONTROLLER_ATTRIB_e */ + ); + +#endif /* _DMACHW_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h new file mode 100644 index 0000000000000..375066ad0186e --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h @@ -0,0 +1,145 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dmacHw_priv.h +* +* @brief Private Definitions for low level DMA driver +* +*/ +/****************************************************************************/ + +#ifndef _DMACHW_PRIV_H +#define _DMACHW_PRIV_H + +#include <csp/stdint.h> + +/* Data type for DMA Link List Item */ +typedef struct { + uint32_t sar; /* Source Adress Register. + Address must be aligned to CTLx.SRC_TR_WIDTH. */ + uint32_t dar; /* Destination Address Register. + Address must be aligned to CTLx.DST_TR_WIDTH. */ + uint32_t llpPhy; /* LLP contains the physical address of the next descriptor for block chaining using linked lists. + Address MUST be aligned to a 32-bit boundary. */ + dmacHw_REG64_t ctl; /* Control Register. 64 bits */ + uint32_t sstat; /* Source Status Register */ + uint32_t dstat; /* Destination Status Register */ + uint32_t devCtl; /* Device specific control information */ + uint32_t llp; /* LLP contains the virtual address of the next descriptor for block chaining using linked lists. */ +} dmacHw_DESC_t; + +/* + * Descriptor ring pointers + */ +typedef struct { + int num; /* Number of link items */ + dmacHw_DESC_t *pHead; /* Head of descriptor ring (for writing) */ + dmacHw_DESC_t *pTail; /* Tail of descriptor ring (for reading) */ + dmacHw_DESC_t *pProg; /* Descriptor to program the channel (for programming the channel register) */ + dmacHw_DESC_t *pEnd; /* End of current descriptor chain */ + dmacHw_DESC_t *pFree; /* Descriptor to free memory (freeing dynamic memory) */ + uint32_t virt2PhyOffset; /* Virtual to physical address offset for the descriptor ring */ +} dmacHw_DESC_RING_t; + +/* + * DMA channel control block + */ +typedef struct { + uint32_t module; /* DMA controller module (0-1) */ + uint32_t channel; /* DMA channel (0-7) */ + volatile uint32_t varDataStarted; /* Flag indicating variable data channel is enabled */ + volatile uint32_t descUpdated; /* Flag to indicate descriptor update is complete */ + void *userData; /* Channel specifc user data */ +} dmacHw_CBLK_t; + +#define dmacHw_ASSERT(a) if (!(a)) while (1) +#define dmacHw_MAX_CHANNEL_COUNT 16 +#define dmacHw_FREE_USER_MEMORY 0xFFFFFFFF +#define dmacHw_DESC_FREE dmacHw_REG_CTL_DONE +#define dmacHw_DESC_INIT ((dmacHw_DESC_t *) 0xFFFFFFFF) +#define dmacHw_MAX_BLOCKSIZE 4064 +#define dmacHw_GET_DESC_RING(addr) (dmacHw_DESC_RING_t *)(addr) +#define dmacHw_ADDRESS_MASK(byte) ((byte) - 1) +#define dmacHw_NEXT_DESC(rp, dp) ((rp)->dp = (dmacHw_DESC_t *)(rp)->dp->llp) +#define dmacHw_HANDLE_TO_CBLK(handle) ((dmacHw_CBLK_t *) (handle)) +#define dmacHw_CBLK_TO_HANDLE(cblkp) ((dmacHw_HANDLE_t) (cblkp)) +#define dmacHw_DST_IS_MEMORY(tt) (((tt) == dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM) || ((tt) == dmacHw_TRANSFER_TYPE_MEM_TO_MEM)) ? 1 : 0 + +/****************************************************************************/ +/** +* @brief Get next available transaction width +* +* +* @return On sucess : Next avail able transaction width +* On failure : dmacHw_TRANSACTION_WIDTH_8 +* +* @note +* None +*/ +/****************************************************************************/ +static inline dmacHw_TRANSACTION_WIDTH_e dmacHw_GetNextTrWidth(dmacHw_TRANSACTION_WIDTH_e tw /* [ IN ] Current transaction width */ + ) { + if (tw & dmacHw_REG_CTL_SRC_TR_WIDTH_MASK) { + return ((tw >> dmacHw_REG_CTL_SRC_TR_WIDTH_SHIFT) - + 1) << dmacHw_REG_CTL_SRC_TR_WIDTH_SHIFT; + } else if (tw & dmacHw_REG_CTL_DST_TR_WIDTH_MASK) { + return ((tw >> dmacHw_REG_CTL_DST_TR_WIDTH_SHIFT) - + 1) << dmacHw_REG_CTL_DST_TR_WIDTH_SHIFT; + } + + /* Default return */ + return dmacHw_SRC_TRANSACTION_WIDTH_8; +} + +/****************************************************************************/ +/** +* @brief Get number of bytes per transaction +* +* @return Number of bytes per transaction +* +* +* @note +* None +*/ +/****************************************************************************/ +static inline int dmacHw_GetTrWidthInBytes(dmacHw_TRANSACTION_WIDTH_e tw /* [ IN ] Transaction width */ + ) { + int width = 1; + switch (tw) { + case dmacHw_SRC_TRANSACTION_WIDTH_8: + width = 1; + break; + case dmacHw_SRC_TRANSACTION_WIDTH_16: + case dmacHw_DST_TRANSACTION_WIDTH_16: + width = 2; + break; + case dmacHw_SRC_TRANSACTION_WIDTH_32: + case dmacHw_DST_TRANSACTION_WIDTH_32: + width = 4; + break; + case dmacHw_SRC_TRANSACTION_WIDTH_64: + case dmacHw_DST_TRANSACTION_WIDTH_64: + width = 8; + break; + default: + dmacHw_ASSERT(0); + } + + /* Default transaction width */ + return width; +} + +#endif /* _DMACHW_PRIV_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h new file mode 100644 index 0000000000000..891cea87e333e --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h @@ -0,0 +1,406 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dmacHw_reg.h +* +* @brief Definitions for low level DMA registers +* +*/ +/****************************************************************************/ + +#ifndef _DMACHW_REG_H +#define _DMACHW_REG_H + +#include <csp/stdint.h> +#include <mach/csp/mm_io.h> + +/* Data type for 64 bit little endian register */ +typedef struct { + volatile uint32_t lo; /* Lower 32 bit in little endian mode */ + volatile uint32_t hi; /* Upper 32 bit in little endian mode */ +} dmacHw_REG64_t; + +/* Data type representing DMA channel registers */ +typedef struct { + dmacHw_REG64_t ChannelSar; /* Source Adress Register. 64 bits (upper 32 bits are reserved) + Address must be aligned to CTLx.SRC_TR_WIDTH. + */ + dmacHw_REG64_t ChannelDar; /* Destination Address Register.64 bits (upper 32 bits are reserved) + Address must be aligned to CTLx.DST_TR_WIDTH. + */ + dmacHw_REG64_t ChannelLlp; /* Link List Pointer.64 bits (upper 32 bits are reserved) + LLP contains the pointer to the next LLI for block chaining using linked lists. + If LLPis set to 0x0, then transfers using linked lists are not enabled. + Address MUST be aligned to a 32-bit boundary. + */ + dmacHw_REG64_t ChannelCtl; /* Control Register. 64 bits */ + dmacHw_REG64_t ChannelSstat; /* Source Status Register */ + dmacHw_REG64_t ChannelDstat; /* Destination Status Register */ + dmacHw_REG64_t ChannelSstatAddr; /* Source Status Address Register */ + dmacHw_REG64_t ChannelDstatAddr; /* Destination Status Address Register */ + dmacHw_REG64_t ChannelConfig; /* Channel Configuration Register */ + dmacHw_REG64_t SrcGather; /* Source gather register */ + dmacHw_REG64_t DstScatter; /* Destination scatter register */ +} dmacHw_CH_REG_t; + +/* Data type for RAW interrupt status registers */ +typedef struct { + dmacHw_REG64_t RawTfr; /* Raw Status for IntTfr Interrupt */ + dmacHw_REG64_t RawBlock; /* Raw Status for IntBlock Interrupt */ + dmacHw_REG64_t RawSrcTran; /* Raw Status for IntSrcTran Interrupt */ + dmacHw_REG64_t RawDstTran; /* Raw Status for IntDstTran Interrupt */ + dmacHw_REG64_t RawErr; /* Raw Status for IntErr Interrupt */ +} dmacHw_INT_RAW_t; + +/* Data type for interrupt status registers */ +typedef struct { + dmacHw_REG64_t StatusTfr; /* Status for IntTfr Interrupt */ + dmacHw_REG64_t StatusBlock; /* Status for IntBlock Interrupt */ + dmacHw_REG64_t StatusSrcTran; /* Status for IntSrcTran Interrupt */ + dmacHw_REG64_t StatusDstTran; /* Status for IntDstTran Interrupt */ + dmacHw_REG64_t StatusErr; /* Status for IntErr Interrupt */ +} dmacHw_INT_STATUS_t; + +/* Data type for interrupt mask registers*/ +typedef struct { + dmacHw_REG64_t MaskTfr; /* Mask for IntTfr Interrupt */ + dmacHw_REG64_t MaskBlock; /* Mask for IntBlock Interrupt */ + dmacHw_REG64_t MaskSrcTran; /* Mask for IntSrcTran Interrupt */ + dmacHw_REG64_t MaskDstTran; /* Mask for IntDstTran Interrupt */ + dmacHw_REG64_t MaskErr; /* Mask for IntErr Interrupt */ +} dmacHw_INT_MASK_t; + +/* Data type for interrupt clear registers */ +typedef struct { + dmacHw_REG64_t ClearTfr; /* Clear for IntTfr Interrupt */ + dmacHw_REG64_t ClearBlock; /* Clear for IntBlock Interrupt */ + dmacHw_REG64_t ClearSrcTran; /* Clear for IntSrcTran Interrupt */ + dmacHw_REG64_t ClearDstTran; /* Clear for IntDstTran Interrupt */ + dmacHw_REG64_t ClearErr; /* Clear for IntErr Interrupt */ + dmacHw_REG64_t StatusInt; /* Status for each interrupt type */ +} dmacHw_INT_CLEAR_t; + +/* Data type for software handshaking registers */ +typedef struct { + dmacHw_REG64_t ReqSrcReg; /* Source Software Transaction Request Register */ + dmacHw_REG64_t ReqDstReg; /* Destination Software Transaction Request Register */ + dmacHw_REG64_t SglReqSrcReg; /* Single Source Transaction Request Register */ + dmacHw_REG64_t SglReqDstReg; /* Single Destination Transaction Request Register */ + dmacHw_REG64_t LstSrcReg; /* Last Source Transaction Request Register */ + dmacHw_REG64_t LstDstReg; /* Last Destination Transaction Request Register */ +} dmacHw_SW_HANDSHAKE_t; + +/* Data type for misc. registers */ +typedef struct { + dmacHw_REG64_t DmaCfgReg; /* DMA Configuration Register */ + dmacHw_REG64_t ChEnReg; /* DMA Channel Enable Register */ + dmacHw_REG64_t DmaIdReg; /* DMA ID Register */ + dmacHw_REG64_t DmaTestReg; /* DMA Test Register */ + dmacHw_REG64_t Reserved0; /* Reserved */ + dmacHw_REG64_t Reserved1; /* Reserved */ + dmacHw_REG64_t CompParm6; /* Component Parameter 6 */ + dmacHw_REG64_t CompParm5; /* Component Parameter 5 */ + dmacHw_REG64_t CompParm4; /* Component Parameter 4 */ + dmacHw_REG64_t CompParm3; /* Component Parameter 3 */ + dmacHw_REG64_t CompParm2; /* Component Parameter 2 */ + dmacHw_REG64_t CompParm1; /* Component Parameter 1 */ + dmacHw_REG64_t CompId; /* Compoent ID */ +} dmacHw_MISC_t; + +/* Base registers */ +#define dmacHw_0_MODULE_BASE_ADDR (char *) MM_IO_BASE_DMA0 /* DMAC 0 module's base address */ +#define dmacHw_1_MODULE_BASE_ADDR (char *) MM_IO_BASE_DMA1 /* DMAC 1 module's base address */ + +extern uint32_t dmaChannelCount_0; +extern uint32_t dmaChannelCount_1; + +/* Define channel specific registers */ +#define dmacHw_CHAN_BASE(module, chan) ((dmacHw_CH_REG_t *) ((char *)((module) ? dmacHw_1_MODULE_BASE_ADDR : dmacHw_0_MODULE_BASE_ADDR) + ((chan) * sizeof(dmacHw_CH_REG_t)))) + +/* Raw interrupt status registers */ +#define dmacHw_REG_INT_RAW_BASE(module) ((char *)dmacHw_CHAN_BASE((module), ((module) ? dmaChannelCount_1 : dmaChannelCount_0))) +#define dmacHw_REG_INT_RAW_TRAN(module) (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawTfr.lo) +#define dmacHw_REG_INT_RAW_BLOCK(module) (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawBlock.lo) +#define dmacHw_REG_INT_RAW_STRAN(module) (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawSrcTran.lo) +#define dmacHw_REG_INT_RAW_DTRAN(module) (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawDstTran.lo) +#define dmacHw_REG_INT_RAW_ERROR(module) (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawErr.lo) + +/* Interrupt status registers */ +#define dmacHw_REG_INT_STAT_BASE(module) ((char *)(dmacHw_REG_INT_RAW_BASE((module)) + sizeof(dmacHw_INT_RAW_t))) +#define dmacHw_REG_INT_STAT_TRAN(module) (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusTfr.lo) +#define dmacHw_REG_INT_STAT_BLOCK(module) (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusBlock.lo) +#define dmacHw_REG_INT_STAT_STRAN(module) (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusSrcTran.lo) +#define dmacHw_REG_INT_STAT_DTRAN(module) (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusDstTran.lo) +#define dmacHw_REG_INT_STAT_ERROR(module) (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusErr.lo) + +/* Interrupt status registers */ +#define dmacHw_REG_INT_MASK_BASE(module) ((char *)(dmacHw_REG_INT_STAT_BASE((module)) + sizeof(dmacHw_INT_STATUS_t))) +#define dmacHw_REG_INT_MASK_TRAN(module) (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskTfr.lo) +#define dmacHw_REG_INT_MASK_BLOCK(module) (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskBlock.lo) +#define dmacHw_REG_INT_MASK_STRAN(module) (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskSrcTran.lo) +#define dmacHw_REG_INT_MASK_DTRAN(module) (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskDstTran.lo) +#define dmacHw_REG_INT_MASK_ERROR(module) (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskErr.lo) + +/* Interrupt clear registers */ +#define dmacHw_REG_INT_CLEAR_BASE(module) ((char *)(dmacHw_REG_INT_MASK_BASE((module)) + sizeof(dmacHw_INT_MASK_t))) +#define dmacHw_REG_INT_CLEAR_TRAN(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearTfr.lo) +#define dmacHw_REG_INT_CLEAR_BLOCK(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearBlock.lo) +#define dmacHw_REG_INT_CLEAR_STRAN(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearSrcTran.lo) +#define dmacHw_REG_INT_CLEAR_DTRAN(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearDstTran.lo) +#define dmacHw_REG_INT_CLEAR_ERROR(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearErr.lo) +#define dmacHw_REG_INT_STATUS(module) (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->StatusInt.lo) + +/* Software handshaking registers */ +#define dmacHw_REG_SW_HS_BASE(module) ((char *)(dmacHw_REG_INT_CLEAR_BASE((module)) + sizeof(dmacHw_INT_CLEAR_t))) +#define dmacHw_REG_SW_HS_SRC_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->ReqSrcReg.lo) +#define dmacHw_REG_SW_HS_DST_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->ReqDstReg.lo) +#define dmacHw_REG_SW_HS_SRC_SGL_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->SglReqSrcReg.lo) +#define dmacHw_REG_SW_HS_DST_SGL_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->SglReqDstReg.lo) +#define dmacHw_REG_SW_HS_SRC_LST_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->LstSrcReg.lo) +#define dmacHw_REG_SW_HS_DST_LST_REQ(module) (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->LstDstReg.lo) + +/* Miscellaneous registers */ +#define dmacHw_REG_MISC_BASE(module) ((char *)(dmacHw_REG_SW_HS_BASE((module)) + sizeof(dmacHw_SW_HANDSHAKE_t))) +#define dmacHw_REG_MISC_CFG(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaCfgReg.lo) +#define dmacHw_REG_MISC_CH_ENABLE(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->ChEnReg.lo) +#define dmacHw_REG_MISC_ID(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaIdReg.lo) +#define dmacHw_REG_MISC_TEST(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaTestReg.lo) +#define dmacHw_REG_MISC_COMP_PARAM1_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm1.lo) +#define dmacHw_REG_MISC_COMP_PARAM1_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm1.hi) +#define dmacHw_REG_MISC_COMP_PARAM2_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm2.lo) +#define dmacHw_REG_MISC_COMP_PARAM2_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm2.hi) +#define dmacHw_REG_MISC_COMP_PARAM3_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm3.lo) +#define dmacHw_REG_MISC_COMP_PARAM3_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm3.hi) +#define dmacHw_REG_MISC_COMP_PARAM4_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm4.lo) +#define dmacHw_REG_MISC_COMP_PARAM4_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm4.hi) +#define dmacHw_REG_MISC_COMP_PARAM5_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm5.lo) +#define dmacHw_REG_MISC_COMP_PARAM5_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm5.hi) +#define dmacHw_REG_MISC_COMP_PARAM6_LO(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm6.lo) +#define dmacHw_REG_MISC_COMP_PARAM6_HI(module) (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm6.hi) + +/* Channel control registers */ +#define dmacHw_REG_SAR(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelSar.lo) +#define dmacHw_REG_DAR(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelDar.lo) +#define dmacHw_REG_LLP(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelLlp.lo) + +#define dmacHw_REG_CTL_LO(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelCtl.lo) +#define dmacHw_REG_CTL_HI(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelCtl.hi) + +#define dmacHw_REG_SSTAT(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelSstat.lo) +#define dmacHw_REG_DSTAT(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelDstat.lo) +#define dmacHw_REG_SSTATAR(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelSstatAddr.lo) +#define dmacHw_REG_DSTATAR(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelDstatAddr.lo) + +#define dmacHw_REG_CFG_LO(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelConfig.lo) +#define dmacHw_REG_CFG_HI(module, chan) (dmacHw_CHAN_BASE((module), (chan))->ChannelConfig.hi) + +#define dmacHw_REG_SGR_LO(module, chan) (dmacHw_CHAN_BASE((module), (chan))->SrcGather.lo) +#define dmacHw_REG_SGR_HI(module, chan) (dmacHw_CHAN_BASE((module), (chan))->SrcGather.hi) + +#define dmacHw_REG_DSR_LO(module, chan) (dmacHw_CHAN_BASE((module), (chan))->DstScatter.lo) +#define dmacHw_REG_DSR_HI(module, chan) (dmacHw_CHAN_BASE((module), (chan))->DstScatter.hi) + +#define INT_STATUS_MASK(channel) (0x00000001 << (channel)) +#define CHANNEL_BUSY(mod, channel) (dmacHw_REG_MISC_CH_ENABLE((mod)) & (0x00000001 << (channel))) + +/* Bit mask for REG_DMACx_CTL_LO */ + +#define dmacHw_REG_CTL_INT_EN 0x00000001 /* Channel interrupt enable */ + +#define dmacHw_REG_CTL_DST_TR_WIDTH_MASK 0x0000000E /* Destination transaction width mask */ +#define dmacHw_REG_CTL_DST_TR_WIDTH_SHIFT 1 +#define dmacHw_REG_CTL_DST_TR_WIDTH_8 0x00000000 /* Destination transaction width 8 bit */ +#define dmacHw_REG_CTL_DST_TR_WIDTH_16 0x00000002 /* Destination transaction width 16 bit */ +#define dmacHw_REG_CTL_DST_TR_WIDTH_32 0x00000004 /* Destination transaction width 32 bit */ +#define dmacHw_REG_CTL_DST_TR_WIDTH_64 0x00000006 /* Destination transaction width 64 bit */ + +#define dmacHw_REG_CTL_SRC_TR_WIDTH_MASK 0x00000070 /* Source transaction width mask */ +#define dmacHw_REG_CTL_SRC_TR_WIDTH_SHIFT 4 +#define dmacHw_REG_CTL_SRC_TR_WIDTH_8 0x00000000 /* Source transaction width 8 bit */ +#define dmacHw_REG_CTL_SRC_TR_WIDTH_16 0x00000010 /* Source transaction width 16 bit */ +#define dmacHw_REG_CTL_SRC_TR_WIDTH_32 0x00000020 /* Source transaction width 32 bit */ +#define dmacHw_REG_CTL_SRC_TR_WIDTH_64 0x00000030 /* Source transaction width 64 bit */ + +#define dmacHw_REG_CTL_DS_ENABLE 0x00040000 /* Destination scatter enable */ +#define dmacHw_REG_CTL_SG_ENABLE 0x00020000 /* Source gather enable */ + +#define dmacHw_REG_CTL_DINC_MASK 0x00000180 /* Destination address inc/dec mask */ +#define dmacHw_REG_CTL_DINC_INC 0x00000000 /* Destination address increment */ +#define dmacHw_REG_CTL_DINC_DEC 0x00000080 /* Destination address decrement */ +#define dmacHw_REG_CTL_DINC_NC 0x00000100 /* Destination address no change */ + +#define dmacHw_REG_CTL_SINC_MASK 0x00000600 /* Source address inc/dec mask */ +#define dmacHw_REG_CTL_SINC_INC 0x00000000 /* Source address increment */ +#define dmacHw_REG_CTL_SINC_DEC 0x00000200 /* Source address decrement */ +#define dmacHw_REG_CTL_SINC_NC 0x00000400 /* Source address no change */ + +#define dmacHw_REG_CTL_DST_MSIZE_MASK 0x00003800 /* Destination burst transaction length */ +#define dmacHw_REG_CTL_DST_MSIZE_0 0x00000000 /* No Destination burst */ +#define dmacHw_REG_CTL_DST_MSIZE_4 0x00000800 /* Destination burst transaction length 4 */ +#define dmacHw_REG_CTL_DST_MSIZE_8 0x00001000 /* Destination burst transaction length 8 */ +#define dmacHw_REG_CTL_DST_MSIZE_16 0x00001800 /* Destination burst transaction length 16 */ + +#define dmacHw_REG_CTL_SRC_MSIZE_MASK 0x0001C000 /* Source burst transaction length */ +#define dmacHw_REG_CTL_SRC_MSIZE_0 0x00000000 /* No Source burst */ +#define dmacHw_REG_CTL_SRC_MSIZE_4 0x00004000 /* Source burst transaction length 4 */ +#define dmacHw_REG_CTL_SRC_MSIZE_8 0x00008000 /* Source burst transaction length 8 */ +#define dmacHw_REG_CTL_SRC_MSIZE_16 0x0000C000 /* Source burst transaction length 16 */ + +#define dmacHw_REG_CTL_TTFC_MASK 0x00700000 /* Transfer type and flow controller */ +#define dmacHw_REG_CTL_TTFC_MM_DMAC 0x00000000 /* Memory to Memory with DMAC as flow controller */ +#define dmacHw_REG_CTL_TTFC_MP_DMAC 0x00100000 /* Memory to Peripheral with DMAC as flow controller */ +#define dmacHw_REG_CTL_TTFC_PM_DMAC 0x00200000 /* Peripheral to Memory with DMAC as flow controller */ +#define dmacHw_REG_CTL_TTFC_PP_DMAC 0x00300000 /* Peripheral to Peripheral with DMAC as flow controller */ +#define dmacHw_REG_CTL_TTFC_PM_PERI 0x00400000 /* Peripheral to Memory with Peripheral as flow controller */ +#define dmacHw_REG_CTL_TTFC_PP_SPERI 0x00500000 /* Peripheral to Peripheral with Source Peripheral as flow controller */ +#define dmacHw_REG_CTL_TTFC_MP_PERI 0x00600000 /* Memory to Peripheral with Peripheral as flow controller */ +#define dmacHw_REG_CTL_TTFC_PP_DPERI 0x00700000 /* Peripheral to Peripheral with Destination Peripheral as flow controller */ + +#define dmacHw_REG_CTL_DMS_MASK 0x01800000 /* Destination AHB master interface */ +#define dmacHw_REG_CTL_DMS_1 0x00000000 /* Destination AHB master interface 1 */ +#define dmacHw_REG_CTL_DMS_2 0x00800000 /* Destination AHB master interface 2 */ + +#define dmacHw_REG_CTL_SMS_MASK 0x06000000 /* Source AHB master interface */ +#define dmacHw_REG_CTL_SMS_1 0x00000000 /* Source AHB master interface 1 */ +#define dmacHw_REG_CTL_SMS_2 0x02000000 /* Source AHB master interface 2 */ + +#define dmacHw_REG_CTL_LLP_DST_EN 0x08000000 /* Block chaining enable for destination side */ +#define dmacHw_REG_CTL_LLP_SRC_EN 0x10000000 /* Block chaining enable for source side */ + +/* Bit mask for REG_DMACx_CTL_HI */ +#define dmacHw_REG_CTL_BLOCK_TS_MASK 0x00000FFF /* Block transfer size */ +#define dmacHw_REG_CTL_DONE 0x00001000 /* Block trasnfer done */ + +/* Bit mask for REG_DMACx_CFG_LO */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_SHIFT 5 /* Channel priority shift */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_MASK 0x000000E0 /* Channel priority mask */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_0 0x00000000 /* Channel priority 0 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_1 0x00000020 /* Channel priority 1 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_2 0x00000040 /* Channel priority 2 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_3 0x00000060 /* Channel priority 3 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_4 0x00000080 /* Channel priority 4 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_5 0x000000A0 /* Channel priority 5 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_6 0x000000C0 /* Channel priority 6 */ +#define dmacHw_REG_CFG_LO_CH_PRIORITY_7 0x000000E0 /* Channel priority 7 */ + +#define dmacHw_REG_CFG_LO_CH_SUSPEND 0x00000100 /* Channel suspend */ +#define dmacHw_REG_CFG_LO_CH_FIFO_EMPTY 0x00000200 /* Channel FIFO empty */ +#define dmacHw_REG_CFG_LO_DST_CH_SW_HS 0x00000400 /* Destination channel SW handshaking */ +#define dmacHw_REG_CFG_LO_SRC_CH_SW_HS 0x00000800 /* Source channel SW handshaking */ + +#define dmacHw_REG_CFG_LO_CH_LOCK_MASK 0x00003000 /* Channel locking mask */ +#define dmacHw_REG_CFG_LO_CH_LOCK_DMA 0x00000000 /* Channel lock over the entire DMA transfer operation */ +#define dmacHw_REG_CFG_LO_CH_LOCK_BLOCK 0x00001000 /* Channel lock over the block transfer operation */ +#define dmacHw_REG_CFG_LO_CH_LOCK_TRANS 0x00002000 /* Channel lock over the transaction */ +#define dmacHw_REG_CFG_LO_CH_LOCK_ENABLE 0x00010000 /* Channel lock enable */ + +#define dmacHw_REG_CFG_LO_BUS_LOCK_MASK 0x0000C000 /* Bus locking mask */ +#define dmacHw_REG_CFG_LO_BUS_LOCK_DMA 0x00000000 /* Bus lock over the entire DMA transfer operation */ +#define dmacHw_REG_CFG_LO_BUS_LOCK_BLOCK 0x00004000 /* Bus lock over the block transfer operation */ +#define dmacHw_REG_CFG_LO_BUS_LOCK_TRANS 0x00008000 /* Bus lock over the transaction */ +#define dmacHw_REG_CFG_LO_BUS_LOCK_ENABLE 0x00020000 /* Bus lock enable */ + +#define dmacHw_REG_CFG_LO_DST_HS_POLARITY_LOW 0x00040000 /* Destination channel handshaking signal polarity low */ +#define dmacHw_REG_CFG_LO_SRC_HS_POLARITY_LOW 0x00080000 /* Source channel handshaking signal polarity low */ + +#define dmacHw_REG_CFG_LO_MAX_AMBA_BURST_LEN_MASK 0x3FF00000 /* Maximum AMBA burst length */ + +#define dmacHw_REG_CFG_LO_AUTO_RELOAD_SRC 0x40000000 /* Source address auto reload */ +#define dmacHw_REG_CFG_LO_AUTO_RELOAD_DST 0x80000000 /* Destination address auto reload */ + +/* Bit mask for REG_DMACx_CFG_HI */ +#define dmacHw_REG_CFG_HI_FC_DST_READY 0x00000001 /* Source transaction request is serviced when destination is ready */ +#define dmacHw_REG_CFG_HI_FIFO_ENOUGH 0x00000002 /* Initiate burst transaction when enough data in available in FIFO */ + +#define dmacHw_REG_CFG_HI_AHB_HPROT_MASK 0x0000001C /* AHB protection mask */ +#define dmacHw_REG_CFG_HI_AHB_HPROT_1 0x00000004 /* AHB protection 1 */ +#define dmacHw_REG_CFG_HI_AHB_HPROT_2 0x00000008 /* AHB protection 2 */ +#define dmacHw_REG_CFG_HI_AHB_HPROT_3 0x00000010 /* AHB protection 3 */ + +#define dmacHw_REG_CFG_HI_UPDATE_DST_STAT 0x00000020 /* Destination status update enable */ +#define dmacHw_REG_CFG_HI_UPDATE_SRC_STAT 0x00000040 /* Source status update enable */ + +#define dmacHw_REG_CFG_HI_SRC_PERI_INTF_MASK 0x00000780 /* Source peripheral hardware interface mask */ +#define dmacHw_REG_CFG_HI_DST_PERI_INTF_MASK 0x00007800 /* Destination peripheral hardware interface mask */ + +/* DMA Configuration Parameters */ +#define dmacHw_REG_COMP_PARAM_NUM_CHANNELS 0x00000700 /* Number of channels */ +#define dmacHw_REG_COMP_PARAM_NUM_INTERFACE 0x00001800 /* Number of master interface */ +#define dmacHw_REG_COMP_PARAM_MAX_BLK_SIZE 0x0000000f /* Maximum brust size */ +#define dmacHw_REG_COMP_PARAM_DATA_WIDTH 0x00006000 /* Data transfer width */ + +/* Define GET/SET macros to program the registers */ +#define dmacHw_SET_SAR(module, channel, addr) (dmacHw_REG_SAR((module), (channel)) = (uint32_t) (addr)) +#define dmacHw_SET_DAR(module, channel, addr) (dmacHw_REG_DAR((module), (channel)) = (uint32_t) (addr)) +#define dmacHw_SET_LLP(module, channel, ptr) (dmacHw_REG_LLP((module), (channel)) = (uint32_t) (ptr)) + +#define dmacHw_GET_SSTAT(module, channel) (dmacHw_REG_SSTAT((module), (channel))) +#define dmacHw_GET_DSTAT(module, channel) (dmacHw_REG_DSTAT((module), (channel))) + +#define dmacHw_SET_SSTATAR(module, channel, addr) (dmacHw_REG_SSTATAR((module), (channel)) = (uint32_t) (addr)) +#define dmacHw_SET_DSTATAR(module, channel, addr) (dmacHw_REG_DSTATAR((module), (channel)) = (uint32_t) (addr)) + +#define dmacHw_SET_CONTROL_LO(module, channel, ctl) (dmacHw_REG_CTL_LO((module), (channel)) |= (ctl)) +#define dmacHw_RESET_CONTROL_LO(module, channel) (dmacHw_REG_CTL_LO((module), (channel)) = 0) +#define dmacHw_GET_CONTROL_LO(module, channel) (dmacHw_REG_CTL_LO((module), (channel))) + +#define dmacHw_SET_CONTROL_HI(module, channel, ctl) (dmacHw_REG_CTL_HI((module), (channel)) |= (ctl)) +#define dmacHw_RESET_CONTROL_HI(module, channel) (dmacHw_REG_CTL_HI((module), (channel)) = 0) +#define dmacHw_GET_CONTROL_HI(module, channel) (dmacHw_REG_CTL_HI((module), (channel))) + +#define dmacHw_GET_BLOCK_SIZE(module, channel) (dmacHw_REG_CTL_HI((module), (channel)) & dmacHw_REG_CTL_BLOCK_TS_MASK) +#define dmacHw_DMA_COMPLETE(module, channel) (dmacHw_REG_CTL_HI((module), (channel)) & dmacHw_REG_CTL_DONE) + +#define dmacHw_SET_CONFIG_LO(module, channel, cfg) (dmacHw_REG_CFG_LO((module), (channel)) |= (cfg)) +#define dmacHw_RESET_CONFIG_LO(module, channel) (dmacHw_REG_CFG_LO((module), (channel)) = 0) +#define dmacHw_GET_CONFIG_LO(module, channel) (dmacHw_REG_CFG_LO((module), (channel))) +#define dmacHw_SET_AMBA_BUSRT_LEN(module, channel, len) (dmacHw_REG_CFG_LO((module), (channel)) = (dmacHw_REG_CFG_LO((module), (channel)) & ~(dmacHw_REG_CFG_LO_MAX_AMBA_BURST_LEN_MASK)) | (((len) << 20) & dmacHw_REG_CFG_LO_MAX_AMBA_BURST_LEN_MASK)) +#define dmacHw_SET_CHANNEL_PRIORITY(module, channel, prio) (dmacHw_REG_CFG_LO((module), (channel)) = (dmacHw_REG_CFG_LO((module), (channel)) & ~(dmacHw_REG_CFG_LO_CH_PRIORITY_MASK)) | (prio)) +#define dmacHw_SET_AHB_HPROT(module, channel, protect) (dmacHw_REG_CFG_HI(module, channel) = (dmacHw_REG_CFG_HI((module), (channel)) & ~(dmacHw_REG_CFG_HI_AHB_HPROT_MASK)) | (protect)) + +#define dmacHw_SET_CONFIG_HI(module, channel, cfg) (dmacHw_REG_CFG_HI((module), (channel)) |= (cfg)) +#define dmacHw_RESET_CONFIG_HI(module, channel) (dmacHw_REG_CFG_HI((module), (channel)) = 0) +#define dmacHw_GET_CONFIG_HI(module, channel) (dmacHw_REG_CFG_HI((module), (channel))) +#define dmacHw_SET_SRC_PERI_INTF(module, channel, intf) (dmacHw_REG_CFG_HI((module), (channel)) = (dmacHw_REG_CFG_HI((module), (channel)) & ~(dmacHw_REG_CFG_HI_SRC_PERI_INTF_MASK)) | (((intf) << 7) & dmacHw_REG_CFG_HI_SRC_PERI_INTF_MASK)) +#define dmacHw_SRC_PERI_INTF(intf) (((intf) << 7) & dmacHw_REG_CFG_HI_SRC_PERI_INTF_MASK) +#define dmacHw_SET_DST_PERI_INTF(module, channel, intf) (dmacHw_REG_CFG_HI((module), (channel)) = (dmacHw_REG_CFG_HI((module), (channel)) & ~(dmacHw_REG_CFG_HI_DST_PERI_INTF_MASK)) | (((intf) << 11) & dmacHw_REG_CFG_HI_DST_PERI_INTF_MASK)) +#define dmacHw_DST_PERI_INTF(intf) (((intf) << 11) & dmacHw_REG_CFG_HI_DST_PERI_INTF_MASK) + +#define dmacHw_DMA_START(module, channel) (dmacHw_REG_MISC_CH_ENABLE((module)) = (0x00000001 << ((channel) + 8)) | (0x00000001 << (channel))) +#define dmacHw_DMA_STOP(module, channel) (dmacHw_REG_MISC_CH_ENABLE((module)) = (0x00000001 << ((channel) + 8))) +#define dmacHw_DMA_ENABLE(module) (dmacHw_REG_MISC_CFG((module)) = 1) +#define dmacHw_DMA_DISABLE(module) (dmacHw_REG_MISC_CFG((module)) = 0) + +#define dmacHw_TRAN_INT_ENABLE(module, channel) (dmacHw_REG_INT_MASK_TRAN((module)) = (0x00000001 << ((channel) + 8)) | (0x00000001 << (channel))) +#define dmacHw_BLOCK_INT_ENABLE(module, channel) (dmacHw_REG_INT_MASK_BLOCK((module)) = (0x00000001 << ((channel) + 8)) | (0x00000001 << (channel))) +#define dmacHw_ERROR_INT_ENABLE(module, channel) (dmacHw_REG_INT_MASK_ERROR((module)) = (0x00000001 << ((channel) + 8)) | (0x00000001 << (channel))) + +#define dmacHw_TRAN_INT_DISABLE(module, channel) (dmacHw_REG_INT_MASK_TRAN((module)) = (0x00000001 << ((channel) + 8))) +#define dmacHw_BLOCK_INT_DISABLE(module, channel) (dmacHw_REG_INT_MASK_BLOCK((module)) = (0x00000001 << ((channel) + 8))) +#define dmacHw_ERROR_INT_DISABLE(module, channel) (dmacHw_REG_INT_MASK_ERROR((module)) = (0x00000001 << ((channel) + 8))) +#define dmacHw_STRAN_INT_DISABLE(module, channel) (dmacHw_REG_INT_MASK_STRAN((module)) = (0x00000001 << ((channel) + 8))) +#define dmacHw_DTRAN_INT_DISABLE(module, channel) (dmacHw_REG_INT_MASK_DTRAN((module)) = (0x00000001 << ((channel) + 8))) + +#define dmacHw_TRAN_INT_CLEAR(module, channel) (dmacHw_REG_INT_CLEAR_TRAN((module)) = (0x00000001 << (channel))) +#define dmacHw_BLOCK_INT_CLEAR(module, channel) (dmacHw_REG_INT_CLEAR_BLOCK((module)) = (0x00000001 << (channel))) +#define dmacHw_ERROR_INT_CLEAR(module, channel) (dmacHw_REG_INT_CLEAR_ERROR((module)) = (0x00000001 << (channel))) + +#define dmacHw_GET_NUM_CHANNEL(module) (((dmacHw_REG_MISC_COMP_PARAM1_HI((module)) & dmacHw_REG_COMP_PARAM_NUM_CHANNELS) >> 8) + 1) +#define dmacHw_GET_NUM_INTERFACE(module) (((dmacHw_REG_MISC_COMP_PARAM1_HI((module)) & dmacHw_REG_COMP_PARAM_NUM_INTERFACE) >> 11) + 1) +#define dmacHw_GET_MAX_BLOCK_SIZE(module, channel) ((dmacHw_REG_MISC_COMP_PARAM1_LO((module)) >> (4 * (channel))) & dmacHw_REG_COMP_PARAM_MAX_BLK_SIZE) +#define dmacHw_GET_CHANNEL_DATA_WIDTH(module, channel) ((dmacHw_REG_MISC_COMP_PARAM1_HI((module)) & dmacHw_REG_COMP_PARAM_DATA_WIDTH) >> 13) + +#endif /* _DMACHW_REG_H */ -- GitLab From cf2ddacb567e85f40241f67b240fa445db7a424d Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:08:00 +0100 Subject: [PATCH 0988/1002] ARM: 5659/1: bcmring: add csp dmac source files add csp dmac source files Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/csp/dmac/Makefile | 1 + arch/arm/mach-bcmring/csp/dmac/dmacHw.c | 917 +++++++++++++++ arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c | 1017 +++++++++++++++++ 3 files changed, 1935 insertions(+) create mode 100644 arch/arm/mach-bcmring/csp/dmac/Makefile create mode 100644 arch/arm/mach-bcmring/csp/dmac/dmacHw.c create mode 100644 arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c diff --git a/arch/arm/mach-bcmring/csp/dmac/Makefile b/arch/arm/mach-bcmring/csp/dmac/Makefile new file mode 100644 index 0000000000000..fb1104fe56b22 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/dmac/Makefile @@ -0,0 +1 @@ +obj-y += dmacHw.o dmacHw_extra.o \ No newline at end of file diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw.c new file mode 100644 index 0000000000000..7b9bac2d79a58 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/dmac/dmacHw.c @@ -0,0 +1,917 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dmacHw.c +* +* @brief Low level DMA controller driver routines +* +* @note +* +* These routines provide basic DMA functionality only. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ +#include <csp/stdint.h> +#include <csp/string.h> +#include <stddef.h> + +#include <csp/dmacHw.h> +#include <mach/csp/dmacHw_reg.h> +#include <mach/csp/dmacHw_priv.h> +#include <mach/csp/chipcHw_inline.h> + +/* ---- External Function Prototypes ------------------------------------- */ + +/* Allocate DMA control blocks */ +dmacHw_CBLK_t dmacHw_gCblk[dmacHw_MAX_CHANNEL_COUNT]; + +uint32_t dmaChannelCount_0 = dmacHw_MAX_CHANNEL_COUNT / 2; +uint32_t dmaChannelCount_1 = dmacHw_MAX_CHANNEL_COUNT / 2; + +/****************************************************************************/ +/** +* @brief Get maximum FIFO for a DMA channel +* +* @return Maximum allowable FIFO size +* +* +*/ +/****************************************************************************/ +static uint32_t GetFifoSize(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + uint32_t val = 0; + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + dmacHw_MISC_t *pMiscReg = + (dmacHw_MISC_t *) dmacHw_REG_MISC_BASE(pCblk->module); + + switch (pCblk->channel) { + case 0: + val = (pMiscReg->CompParm2.lo & 0x70000000) >> 28; + break; + case 1: + val = (pMiscReg->CompParm3.hi & 0x70000000) >> 28; + break; + case 2: + val = (pMiscReg->CompParm3.lo & 0x70000000) >> 28; + break; + case 3: + val = (pMiscReg->CompParm4.hi & 0x70000000) >> 28; + break; + case 4: + val = (pMiscReg->CompParm4.lo & 0x70000000) >> 28; + break; + case 5: + val = (pMiscReg->CompParm5.hi & 0x70000000) >> 28; + break; + case 6: + val = (pMiscReg->CompParm5.lo & 0x70000000) >> 28; + break; + case 7: + val = (pMiscReg->CompParm6.hi & 0x70000000) >> 28; + break; + } + + if (val <= 0x4) { + return 8 << val; + } else { + dmacHw_ASSERT(0); + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Program channel register to initiate transfer +* +* @return void +* +* +* @note +* - Descriptor buffer MUST ALWAYS be flushed before calling this function +* - This function should also be called from ISR to program the channel with +* pending descriptors +*/ +/****************************************************************************/ +void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor /* [ IN ] Descriptor buffer */ + ) { + dmacHw_DESC_RING_t *pRing; + dmacHw_DESC_t *pProg; + dmacHw_CBLK_t *pCblk; + + pCblk = dmacHw_HANDLE_TO_CBLK(handle); + pRing = dmacHw_GET_DESC_RING(pDescriptor); + + if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { + /* Not safe yet to program the channel */ + return; + } + + if (pCblk->varDataStarted) { + if (pCblk->descUpdated) { + pCblk->descUpdated = 0; + pProg = + (dmacHw_DESC_t *) ((uint32_t) + dmacHw_REG_LLP(pCblk->module, + pCblk->channel) + + pRing->virt2PhyOffset); + + /* Load descriptor if not loaded */ + if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) { + dmacHw_SET_SAR(pCblk->module, pCblk->channel, + pProg->sar); + dmacHw_SET_DAR(pCblk->module, pCblk->channel, + pProg->dar); + dmacHw_REG_CTL_LO(pCblk->module, + pCblk->channel) = + pProg->ctl.lo; + dmacHw_REG_CTL_HI(pCblk->module, + pCblk->channel) = + pProg->ctl.hi; + } else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) { + /* Return as end descriptor is processed */ + return; + } else { + dmacHw_ASSERT(0); + } + } else { + return; + } + } else { + if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) { + /* Do not make a single chain, rather process one descriptor at a time */ + pProg = pRing->pHead; + /* Point to the next descriptor for next iteration */ + dmacHw_NEXT_DESC(pRing, pHead); + } else { + /* Return if no more pending descriptor */ + if (pRing->pEnd == NULL) { + return; + } + + pProg = pRing->pProg; + if (pConfig->transferMode == + dmacHw_TRANSFER_MODE_CONTINUOUS) { + /* Make sure a complete ring can be formed */ + dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd-> + llp == pRing->pProg); + /* Make sure pProg pointing to the pHead */ + dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg == + pRing->pHead); + /* Make a complete ring */ + do { + pRing->pProg->ctl.lo |= + (dmacHw_REG_CTL_LLP_DST_EN | + dmacHw_REG_CTL_LLP_SRC_EN); + pRing->pProg = + (dmacHw_DESC_t *) pRing->pProg->llp; + } while (pRing->pProg != pRing->pHead); + } else { + /* Make a single long chain */ + while (pRing->pProg != pRing->pEnd) { + pRing->pProg->ctl.lo |= + (dmacHw_REG_CTL_LLP_DST_EN | + dmacHw_REG_CTL_LLP_SRC_EN); + pRing->pProg = + (dmacHw_DESC_t *) pRing->pProg->llp; + } + } + } + + /* Program the channel registers */ + dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); + dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); + dmacHw_SET_LLP(pCblk->module, pCblk->channel, + (uint32_t) pProg - pRing->virt2PhyOffset); + dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = + pProg->ctl.lo; + dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = + pProg->ctl.hi; + if (pRing->pEnd) { + /* Remember the descriptor to use next */ + pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp; + } + /* Indicate no more pending descriptor */ + pRing->pEnd = (dmacHw_DESC_t *) NULL; + } + /* Start DMA operation */ + dmacHw_DMA_START(pCblk->module, pCblk->channel); +} + +/****************************************************************************/ +/** +* @brief Initializes DMA +* +* This function initializes DMA CSP driver +* +* @note +* Must be called before using any DMA channel +*/ +/****************************************************************************/ +void dmacHw_initDma(void) +{ + + uint32_t i = 0; + + dmaChannelCount_0 = dmacHw_GET_NUM_CHANNEL(0); + dmaChannelCount_1 = dmacHw_GET_NUM_CHANNEL(1); + + /* Enable access to the DMA block */ + chipcHw_busInterfaceClockEnable(chipcHw_REG_BUS_CLOCK_DMAC0); + chipcHw_busInterfaceClockEnable(chipcHw_REG_BUS_CLOCK_DMAC1); + + if ((dmaChannelCount_0 + dmaChannelCount_1) > dmacHw_MAX_CHANNEL_COUNT) { + dmacHw_ASSERT(0); + } + + memset((void *)dmacHw_gCblk, 0, + sizeof(dmacHw_CBLK_t) * (dmaChannelCount_0 + dmaChannelCount_1)); + for (i = 0; i < dmaChannelCount_0; i++) { + dmacHw_gCblk[i].module = 0; + dmacHw_gCblk[i].channel = i; + } + for (i = 0; i < dmaChannelCount_1; i++) { + dmacHw_gCblk[i + dmaChannelCount_0].module = 1; + dmacHw_gCblk[i + dmaChannelCount_0].channel = i; + } +} + +/****************************************************************************/ +/** +* @brief Exit function for DMA +* +* This function isolates DMA from the system +* +*/ +/****************************************************************************/ +void dmacHw_exitDma(void) +{ + /* Disable access to the DMA block */ + chipcHw_busInterfaceClockDisable(chipcHw_REG_BUS_CLOCK_DMAC0); + chipcHw_busInterfaceClockDisable(chipcHw_REG_BUS_CLOCK_DMAC1); +} + +/****************************************************************************/ +/** +* @brief Gets a handle to a DMA channel +* +* This function returns a handle, representing a control block of a particular DMA channel +* +* @return -1 - On Failure +* handle - On Success, representing a channel control block +* +* @note +* None Channel ID must be created using "dmacHw_MAKE_CHANNEL_ID" macro +*/ +/****************************************************************************/ +dmacHw_HANDLE_t dmacHw_getChannelHandle(dmacHw_ID_t channelId /* [ IN ] DMA Channel Id */ + ) { + int idx; + + switch ((channelId >> 8)) { + case 0: + dmacHw_ASSERT((channelId & 0xff) < dmaChannelCount_0); + idx = (channelId & 0xff); + break; + case 1: + dmacHw_ASSERT((channelId & 0xff) < dmaChannelCount_1); + idx = dmaChannelCount_0 + (channelId & 0xff); + break; + default: + dmacHw_ASSERT(0); + return (dmacHw_HANDLE_t) -1; + } + + return dmacHw_CBLK_TO_HANDLE(&dmacHw_gCblk[idx]); +} + +/****************************************************************************/ +/** +* @brief Initializes a DMA channel for use +* +* This function initializes and resets a DMA channel for use +* +* @return -1 - On Failure +* 0 - On Success +* +* @note +* None +*/ +/****************************************************************************/ +int dmacHw_initChannel(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + int module = pCblk->module; + int channel = pCblk->channel; + + /* Reinitialize the control block */ + memset((void *)pCblk, 0, sizeof(dmacHw_CBLK_t)); + pCblk->module = module; + pCblk->channel = channel; + + /* Enable DMA controller */ + dmacHw_DMA_ENABLE(pCblk->module); + /* Reset DMA channel */ + dmacHw_RESET_CONTROL_LO(pCblk->module, pCblk->channel); + dmacHw_RESET_CONTROL_HI(pCblk->module, pCblk->channel); + dmacHw_RESET_CONFIG_LO(pCblk->module, pCblk->channel); + dmacHw_RESET_CONFIG_HI(pCblk->module, pCblk->channel); + + /* Clear all raw interrupt status */ + dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); + + /* Mask event specific interrupts */ + dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); + dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); + dmacHw_STRAN_INT_DISABLE(pCblk->module, pCblk->channel); + dmacHw_DTRAN_INT_DISABLE(pCblk->module, pCblk->channel); + dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); + + return 0; +} + +/****************************************************************************/ +/** +* @brief Finds amount of memory required to form a descriptor ring +* +* +* @return Number of bytes required to form a descriptor ring +* +* +*/ +/****************************************************************************/ +uint32_t dmacHw_descriptorLen(uint32_t descCnt /* [ IN ] Number of descriptor in the ring */ + ) { + /* Need extra 4 byte to ensure 32 bit alignment */ + return (descCnt * sizeof(dmacHw_DESC_t)) + sizeof(dmacHw_DESC_RING_t) + + sizeof(uint32_t); +} + +/****************************************************************************/ +/** +* @brief Initializes descriptor ring +* +* This function will initializes the descriptor ring of a DMA channel +* +* +* @return -1 - On failure +* 0 - On success +* @note +* - "len" parameter should be obtained from "dmacHw_descriptorLen" +* - Descriptor buffer MUST be 32 bit aligned and uncached as it is +* accessed by ARM and DMA +*/ +/****************************************************************************/ +int dmacHw_initDescriptor(void *pDescriptorVirt, /* [ IN ] Virtual address of uncahced buffer allocated to form descriptor ring */ + uint32_t descriptorPhyAddr, /* [ IN ] Physical address of pDescriptorVirt (descriptor buffer) */ + uint32_t len, /* [ IN ] Size of the pBuf */ + uint32_t num /* [ IN ] Number of descriptor in the ring */ + ) { + uint32_t i; + dmacHw_DESC_RING_t *pRing; + dmacHw_DESC_t *pDesc; + + /* Check the alignment of the descriptor */ + if ((uint32_t) pDescriptorVirt & 0x00000003) { + dmacHw_ASSERT(0); + return -1; + } + + /* Check if enough space has been allocated for descriptor ring */ + if (len < dmacHw_descriptorLen(num)) { + return -1; + } + + pRing = dmacHw_GET_DESC_RING(pDescriptorVirt); + pRing->pHead = + (dmacHw_DESC_t *) ((uint32_t) pRing + sizeof(dmacHw_DESC_RING_t)); + pRing->pFree = pRing->pTail = pRing->pEnd = pRing->pHead; + pRing->pProg = dmacHw_DESC_INIT; + /* Initialize link item chain, starting from the head */ + pDesc = pRing->pHead; + /* Find the offset between virtual to physical address */ + pRing->virt2PhyOffset = (uint32_t) pDescriptorVirt - descriptorPhyAddr; + + /* Form the descriptor ring */ + for (i = 0; i < num - 1; i++) { + /* Clear link list item */ + memset((void *)pDesc, 0, sizeof(dmacHw_DESC_t)); + /* Point to the next item in the physical address */ + pDesc->llpPhy = (uint32_t) (pDesc + 1) - pRing->virt2PhyOffset; + /* Point to the next item in the virtual address */ + pDesc->llp = (uint32_t) (pDesc + 1); + /* Mark descriptor is ready to use */ + pDesc->ctl.hi = dmacHw_DESC_FREE; + /* Look into next link list item */ + pDesc++; + } + + /* Clear last link list item */ + memset((void *)pDesc, 0, sizeof(dmacHw_DESC_t)); + /* Last item pointing to the first item in the + physical address to complete the ring */ + pDesc->llpPhy = (uint32_t) pRing->pHead - pRing->virt2PhyOffset; + /* Last item pointing to the first item in the + virtual address to complete the ring + */ + pDesc->llp = (uint32_t) pRing->pHead; + /* Mark descriptor is ready to use */ + pDesc->ctl.hi = dmacHw_DESC_FREE; + /* Set the number of descriptors in the ring */ + pRing->num = num; + return 0; +} + +/****************************************************************************/ +/** +* @brief Configure DMA channel +* +* @return 0 : On success +* -1 : On failure +*/ +/****************************************************************************/ +int dmacHw_configChannel(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig /* [ IN ] Configuration settings */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + uint32_t cfgHigh = 0; + int srcTrSize; + int dstTrSize; + + pCblk->varDataStarted = 0; + pCblk->userData = NULL; + + /* Configure + - Burst transaction when enough data in available in FIFO + - AHB Access protection 1 + - Source and destination peripheral ports + */ + cfgHigh = + dmacHw_REG_CFG_HI_FIFO_ENOUGH | dmacHw_REG_CFG_HI_AHB_HPROT_1 | + dmacHw_SRC_PERI_INTF(pConfig-> + srcPeripheralPort) | + dmacHw_DST_PERI_INTF(pConfig->dstPeripheralPort); + /* Set priority */ + dmacHw_SET_CHANNEL_PRIORITY(pCblk->module, pCblk->channel, + pConfig->channelPriority); + + if (pConfig->dstStatusRegisterAddress != 0) { + /* Destination status update enable */ + cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_DST_STAT; + /* Configure status registers */ + dmacHw_SET_DSTATAR(pCblk->module, pCblk->channel, + pConfig->dstStatusRegisterAddress); + } + + if (pConfig->srcStatusRegisterAddress != 0) { + /* Source status update enable */ + cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_SRC_STAT; + /* Source status update enable */ + dmacHw_SET_SSTATAR(pCblk->module, pCblk->channel, + pConfig->srcStatusRegisterAddress); + } + /* Configure the config high register */ + dmacHw_GET_CONFIG_HI(pCblk->module, pCblk->channel) = cfgHigh; + + /* Clear all raw interrupt status */ + dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); + + /* Configure block interrupt */ + if (pConfig->blockTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { + dmacHw_BLOCK_INT_ENABLE(pCblk->module, pCblk->channel); + } else { + dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); + } + /* Configure complete transfer interrupt */ + if (pConfig->completeTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { + dmacHw_TRAN_INT_ENABLE(pCblk->module, pCblk->channel); + } else { + dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); + } + /* Configure error interrupt */ + if (pConfig->errorInterrupt == dmacHw_INTERRUPT_ENABLE) { + dmacHw_ERROR_INT_ENABLE(pCblk->module, pCblk->channel); + } else { + dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); + } + /* Configure gather register */ + if (pConfig->srcGatherWidth) { + srcTrSize = + dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); + if (! + ((pConfig->srcGatherWidth % srcTrSize) + && (pConfig->srcGatherJump % srcTrSize))) { + dmacHw_REG_SGR_LO(pCblk->module, pCblk->channel) = + ((pConfig->srcGatherWidth / + srcTrSize) << 20) | (pConfig->srcGatherJump / + srcTrSize); + } else { + return -1; + } + } + /* Configure scatter register */ + if (pConfig->dstScatterWidth) { + dstTrSize = + dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); + if (! + ((pConfig->dstScatterWidth % dstTrSize) + && (pConfig->dstScatterJump % dstTrSize))) { + dmacHw_REG_DSR_LO(pCblk->module, pCblk->channel) = + ((pConfig->dstScatterWidth / + dstTrSize) << 20) | (pConfig->dstScatterJump / + dstTrSize); + } else { + return -1; + } + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Indicates whether DMA transfer is in progress or completed +* +* @return DMA transfer status +* dmacHw_TRANSFER_STATUS_BUSY: DMA Transfer ongoing +* dmacHw_TRANSFER_STATUS_DONE: DMA Transfer completed +* dmacHw_TRANSFER_STATUS_ERROR: DMA Transfer error +* +*/ +/****************************************************************************/ +dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { + return dmacHw_TRANSFER_STATUS_BUSY; + } else if (dmacHw_REG_INT_RAW_ERROR(pCblk->module) & + (0x00000001 << pCblk->channel)) { + return dmacHw_TRANSFER_STATUS_ERROR; + } + + return dmacHw_TRANSFER_STATUS_DONE; +} + +/****************************************************************************/ +/** +* @brief Set descriptors for known data length +* +* When DMA has to work as a flow controller, this function prepares the +* descriptor chain to transfer data +* +* from: +* - Memory to memory +* - Peripheral to memory +* - Memory to Peripheral +* - Peripheral to Peripheral +* +* @return -1 - On failure +* 0 - On success +* +*/ +/****************************************************************************/ +int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void *pSrcAddr, /* [ IN ] Source (Peripheral/Memory) address */ + void *pDstAddr, /* [ IN ] Destination (Peripheral/Memory) address */ + size_t dataLen /* [ IN ] Data length in bytes */ + ) { + dmacHw_TRANSACTION_WIDTH_e dstTrWidth; + dmacHw_TRANSACTION_WIDTH_e srcTrWidth; + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + dmacHw_DESC_t *pStart; + dmacHw_DESC_t *pProg; + int srcTs = 0; + int blkTs = 0; + int oddSize = 0; + int descCount = 0; + int count = 0; + int dstTrSize = 0; + int srcTrSize = 0; + uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE; + + dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); + srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); + + /* Skip Tx if buffer is NULL or length is unknown */ + if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) { + /* Do not initiate transfer */ + return -1; + } + + /* Ensure scatter and gather are transaction aligned */ + if ((pConfig->srcGatherWidth % srcTrSize) + || (pConfig->dstScatterWidth % dstTrSize)) { + return -2; + } + + /* + Background 1: DMAC can not perform DMA if source and destination addresses are + not properly aligned with the channel's transaction width. So, for successful + DMA transfer, transaction width must be set according to the alignment of the + source and destination address. + */ + + /* Adjust destination transaction width if destination address is not aligned properly */ + dstTrWidth = pConfig->dstMaxTransactionWidth; + while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) { + dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth); + dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth); + } + + /* Adjust source transaction width if source address is not aligned properly */ + srcTrWidth = pConfig->srcMaxTransactionWidth; + while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) { + srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth); + srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth); + } + + /* Find the maximum transaction per descriptor */ + if (pConfig->maxDataPerBlock + && ((pConfig->maxDataPerBlock / srcTrSize) < + dmacHw_MAX_BLOCKSIZE)) { + maxBlockSize = pConfig->maxDataPerBlock / srcTrSize; + } + + /* Find number of source transactions needed to complete the DMA transfer */ + srcTs = dataLen / srcTrSize; + /* Find the odd number of bytes that need to be transferred as single byte transaction width */ + if (srcTs && (dstTrSize > srcTrSize)) { + oddSize = dataLen % dstTrSize; + /* Adjust source transaction count due to "oddSize" */ + srcTs = srcTs - (oddSize / srcTrSize); + } else { + oddSize = dataLen % srcTrSize; + } + /* Adjust "descCount" due to "oddSize" */ + if (oddSize) { + descCount++; + } + /* Find the number of descriptor needed for total "srcTs" */ + if (srcTs) { + descCount += ((srcTs - 1) / maxBlockSize) + 1; + } + + /* Check the availability of "descCount" discriptors in the ring */ + pProg = pRing->pHead; + for (count = 0; (descCount <= pRing->num) && (count < descCount); + count++) { + if ((pProg->ctl.hi & dmacHw_DESC_FREE) == 0) { + /* Sufficient descriptors are not available */ + return -3; + } + pProg = (dmacHw_DESC_t *) pProg->llp; + } + + /* Remember the link list item to program the channel registers */ + pStart = pProg = pRing->pHead; + /* Make a link list with "descCount(=count)" number of descriptors */ + while (count) { + /* Reset channel control information */ + pProg->ctl.lo = 0; + /* Enable source gather if configured */ + if (pConfig->srcGatherWidth) { + pProg->ctl.lo |= dmacHw_REG_CTL_SG_ENABLE; + } + /* Enable destination scatter if configured */ + if (pConfig->dstScatterWidth) { + pProg->ctl.lo |= dmacHw_REG_CTL_DS_ENABLE; + } + /* Set source and destination address */ + pProg->sar = (uint32_t) pSrcAddr; + pProg->dar = (uint32_t) pDstAddr; + /* Use "devCtl" to mark that user memory need to be freed later if needed */ + if (pProg == pRing->pHead) { + pProg->devCtl = dmacHw_FREE_USER_MEMORY; + } else { + pProg->devCtl = 0; + } + + blkTs = srcTs; + + /* Special treatmeant for last descriptor */ + if (count == 1) { + /* Mark the last descriptor */ + pProg->ctl.lo &= + ~(dmacHw_REG_CTL_LLP_DST_EN | + dmacHw_REG_CTL_LLP_SRC_EN); + /* Treatment for odd data bytes */ + if (oddSize) { + /* Adjust for single byte transaction width */ + switch (pConfig->transferType) { + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: + dstTrWidth = + dmacHw_DST_TRANSACTION_WIDTH_8; + blkTs = + (oddSize / srcTrSize) + + ((oddSize % srcTrSize) ? 1 : 0); + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: + srcTrWidth = + dmacHw_SRC_TRANSACTION_WIDTH_8; + blkTs = oddSize; + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_MEM: + srcTrWidth = + dmacHw_SRC_TRANSACTION_WIDTH_8; + dstTrWidth = + dmacHw_DST_TRANSACTION_WIDTH_8; + blkTs = oddSize; + break; + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL: + /* Do not adjust the transaction width */ + break; + } + } else { + srcTs -= blkTs; + } + } else { + if (srcTs / maxBlockSize) { + blkTs = maxBlockSize; + } + /* Remaining source transactions for next iteration */ + srcTs -= blkTs; + } + /* Must have a valid source transactions */ + dmacHw_ASSERT(blkTs > 0); + /* Set control information */ + if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) { + pProg->ctl.lo |= pConfig->transferType | + pConfig->srcUpdate | + pConfig->dstUpdate | + srcTrWidth | + dstTrWidth | + pConfig->srcMaxBurstWidth | + pConfig->dstMaxBurstWidth | + pConfig->srcMasterInterface | + pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN; + } else { + uint32_t transferType = 0; + switch (pConfig->transferType) { + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: + transferType = dmacHw_REG_CTL_TTFC_PM_PERI; + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: + transferType = dmacHw_REG_CTL_TTFC_MP_PERI; + break; + default: + dmacHw_ASSERT(0); + } + pProg->ctl.lo |= transferType | + pConfig->srcUpdate | + pConfig->dstUpdate | + srcTrWidth | + dstTrWidth | + pConfig->srcMaxBurstWidth | + pConfig->dstMaxBurstWidth | + pConfig->srcMasterInterface | + pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN; + } + + /* Set block transaction size */ + pProg->ctl.hi = blkTs & dmacHw_REG_CTL_BLOCK_TS_MASK; + /* Look for next descriptor */ + if (count > 1) { + /* Point to the next descriptor */ + pProg = (dmacHw_DESC_t *) pProg->llp; + + /* Update source and destination address for next iteration */ + switch (pConfig->transferType) { + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: + if (pConfig->dstScatterWidth) { + pDstAddr = + (char *)pDstAddr + + blkTs * srcTrSize + + (((blkTs * srcTrSize) / + pConfig->dstScatterWidth) * + pConfig->dstScatterJump); + } else { + pDstAddr = + (char *)pDstAddr + + blkTs * srcTrSize; + } + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: + if (pConfig->srcGatherWidth) { + pSrcAddr = + (char *)pDstAddr + + blkTs * srcTrSize + + (((blkTs * srcTrSize) / + pConfig->srcGatherWidth) * + pConfig->srcGatherJump); + } else { + pSrcAddr = + (char *)pSrcAddr + + blkTs * srcTrSize; + } + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_MEM: + if (pConfig->dstScatterWidth) { + pDstAddr = + (char *)pDstAddr + + blkTs * srcTrSize + + (((blkTs * srcTrSize) / + pConfig->dstScatterWidth) * + pConfig->dstScatterJump); + } else { + pDstAddr = + (char *)pDstAddr + + blkTs * srcTrSize; + } + + if (pConfig->srcGatherWidth) { + pSrcAddr = + (char *)pDstAddr + + blkTs * srcTrSize + + (((blkTs * srcTrSize) / + pConfig->srcGatherWidth) * + pConfig->srcGatherJump); + } else { + pSrcAddr = + (char *)pSrcAddr + + blkTs * srcTrSize; + } + break; + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL: + /* Do not adjust the address */ + break; + default: + dmacHw_ASSERT(0); + } + } else { + /* At the end of transfer "srcTs" must be zero */ + dmacHw_ASSERT(srcTs == 0); + } + count--; + } + + /* Remember the descriptor to initialize the registers */ + if (pRing->pProg == dmacHw_DESC_INIT) { + pRing->pProg = pStart; + } + /* Indicate that the descriptor is updated */ + pRing->pEnd = pProg; + /* Head pointing to the next descriptor */ + pRing->pHead = (dmacHw_DESC_t *) pProg->llp; + /* Update Tail pointer if destination is a peripheral, + because no one is going to read from the pTail + */ + if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) { + pRing->pTail = pRing->pHead; + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Provides DMA controller attributes +* +* +* @return DMA controller attributes +* +* @note +* None +*/ +/****************************************************************************/ +uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONTROLLER_ATTRIB_e attr /* [ IN ] DMA Controler attribute of type dmacHw_CONTROLLER_ATTRIB_e */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + switch (attr) { + case dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM: + return dmacHw_GET_NUM_CHANNEL(pCblk->module); + case dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE: + return (1 << + (dmacHw_GET_MAX_BLOCK_SIZE + (pCblk->module, pCblk->module) + 2)) - 8; + case dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM: + return dmacHw_GET_NUM_INTERFACE(pCblk->module); + case dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH: + return 32 << dmacHw_GET_CHANNEL_DATA_WIDTH(pCblk->module, + pCblk->channel); + case dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE: + return GetFifoSize(handle); + } + dmacHw_ASSERT(0); + return 0; +} diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c new file mode 100644 index 0000000000000..ff7b436d09353 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c @@ -0,0 +1,1017 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file dmacHw_extra.c +* +* @brief Extra Low level DMA controller driver routines +* +* @note +* +* These routines provide basic DMA functionality only. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/stdint.h> +#include <stddef.h> + +#include <csp/dmacHw.h> +#include <mach/csp/dmacHw_reg.h> +#include <mach/csp/dmacHw_priv.h> + +extern dmacHw_CBLK_t dmacHw_gCblk[dmacHw_MAX_CHANNEL_COUNT]; /* Declared in dmacHw.c */ + +/* ---- External Function Prototypes ------------------------------------- */ + +/* ---- Internal Use Function Prototypes --------------------------------- */ +/****************************************************************************/ +/** +* @brief Overwrites data length in the descriptor +* +* This function overwrites data length in the descriptor +* +* +* @return void +* +* @note +* This is only used for PCM channel +*/ +/****************************************************************************/ +void dmacHw_setDataLength(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + size_t dataLen /* [ IN ] Data length in bytes */ + ); + +/****************************************************************************/ +/** +* @brief Helper function to display DMA registers +* +* @return void +* +* +* @note +* None +*/ +/****************************************************************************/ +static void DisplayRegisterContents(int module, /* [ IN ] DMA Controller unit (0-1) */ + int channel, /* [ IN ] DMA Channel (0-7) / -1(all) */ + int (*fpPrint) (const char *, ...) /* [ IN ] Callback to the print function */ + ) { + int chan; + + (*fpPrint) ("Displaying register content \n\n"); + (*fpPrint) ("Module %d: Interrupt raw transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_RAW_TRAN(module))); + (*fpPrint) ("Module %d: Interrupt raw block 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_RAW_BLOCK(module))); + (*fpPrint) ("Module %d: Interrupt raw src transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_RAW_STRAN(module))); + (*fpPrint) ("Module %d: Interrupt raw dst transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_RAW_DTRAN(module))); + (*fpPrint) ("Module %d: Interrupt raw error 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_RAW_ERROR(module))); + (*fpPrint) ("--------------------------------------------------\n"); + (*fpPrint) ("Module %d: Interrupt stat transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_STAT_TRAN(module))); + (*fpPrint) ("Module %d: Interrupt stat block 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_STAT_BLOCK(module))); + (*fpPrint) ("Module %d: Interrupt stat src transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_STAT_STRAN(module))); + (*fpPrint) ("Module %d: Interrupt stat dst transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_STAT_DTRAN(module))); + (*fpPrint) ("Module %d: Interrupt stat error 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_STAT_ERROR(module))); + (*fpPrint) ("--------------------------------------------------\n"); + (*fpPrint) ("Module %d: Interrupt mask transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_MASK_TRAN(module))); + (*fpPrint) ("Module %d: Interrupt mask block 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_MASK_BLOCK(module))); + (*fpPrint) ("Module %d: Interrupt mask src transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_MASK_STRAN(module))); + (*fpPrint) ("Module %d: Interrupt mask dst transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_MASK_DTRAN(module))); + (*fpPrint) ("Module %d: Interrupt mask error 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_MASK_ERROR(module))); + (*fpPrint) ("--------------------------------------------------\n"); + (*fpPrint) ("Module %d: Interrupt clear transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_CLEAR_TRAN(module))); + (*fpPrint) ("Module %d: Interrupt clear block 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_CLEAR_BLOCK(module))); + (*fpPrint) ("Module %d: Interrupt clear src transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_CLEAR_STRAN(module))); + (*fpPrint) ("Module %d: Interrupt clear dst transfer 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_CLEAR_DTRAN(module))); + (*fpPrint) ("Module %d: Interrupt clear error 0x%X\n", + module, (uint32_t) (dmacHw_REG_INT_CLEAR_ERROR(module))); + (*fpPrint) ("--------------------------------------------------\n"); + (*fpPrint) ("Module %d: SW source req 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_SRC_REQ(module))); + (*fpPrint) ("Module %d: SW dest req 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_DST_REQ(module))); + (*fpPrint) ("Module %d: SW source signal 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_SRC_SGL_REQ(module))); + (*fpPrint) ("Module %d: SW dest signal 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_DST_SGL_REQ(module))); + (*fpPrint) ("Module %d: SW source last 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_SRC_LST_REQ(module))); + (*fpPrint) ("Module %d: SW dest last 0x%X\n", + module, (uint32_t) (dmacHw_REG_SW_HS_DST_LST_REQ(module))); + (*fpPrint) ("--------------------------------------------------\n"); + (*fpPrint) ("Module %d: misc config 0x%X\n", + module, (uint32_t) (dmacHw_REG_MISC_CFG(module))); + (*fpPrint) ("Module %d: misc channel enable 0x%X\n", + module, (uint32_t) (dmacHw_REG_MISC_CH_ENABLE(module))); + (*fpPrint) ("Module %d: misc ID 0x%X\n", + module, (uint32_t) (dmacHw_REG_MISC_ID(module))); + (*fpPrint) ("Module %d: misc test 0x%X\n", + module, (uint32_t) (dmacHw_REG_MISC_TEST(module))); + + if (channel == -1) { + for (chan = 0; chan < 8; chan++) { + (*fpPrint) + ("--------------------------------------------------\n"); + (*fpPrint) + ("Module %d: Channel %d Source 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_SAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Destination 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_DAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d LLP 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_LLP(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Control (LO) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CTL_LO(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Control (HI) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CTL_HI(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Source Stats 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_SSTAT(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Dest Stats 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_DSTAT(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Source Stats Addr 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_SSTATAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Dest Stats Addr 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_DSTATAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Config (LO) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CFG_LO(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Config (HI) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CFG_HI(module, chan))); + } + } else { + chan = channel; + (*fpPrint) + ("--------------------------------------------------\n"); + (*fpPrint) + ("Module %d: Channel %d Source 0x%X\n", + module, chan, (uint32_t) (dmacHw_REG_SAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Destination 0x%X\n", + module, chan, (uint32_t) (dmacHw_REG_DAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d LLP 0x%X\n", + module, chan, (uint32_t) (dmacHw_REG_LLP(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Control (LO) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CTL_LO(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Control (HI) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CTL_HI(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Source Stats 0x%X\n", + module, chan, (uint32_t) (dmacHw_REG_SSTAT(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Dest Stats 0x%X\n", + module, chan, (uint32_t) (dmacHw_REG_DSTAT(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Source Stats Addr 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_SSTATAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Dest Stats Addr 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_DSTATAR(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Config (LO) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CFG_LO(module, chan))); + (*fpPrint) + ("Module %d: Channel %d Config (HI) 0x%X\n", + module, chan, + (uint32_t) (dmacHw_REG_CFG_HI(module, chan))); + } +} + +/****************************************************************************/ +/** +* @brief Helper function to display descriptor ring +* +* @return void +* +* +* @note +* None +*/ +/****************************************************************************/ +static void DisplayDescRing(void *pDescriptor, /* [ IN ] Descriptor buffer */ + int (*fpPrint) (const char *, ...) /* [ IN ] Callback to the print function */ + ) { + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + dmacHw_DESC_t *pStart; + + if (pRing->pHead == NULL) { + return; + } + + pStart = pRing->pHead; + + while ((dmacHw_DESC_t *) pStart->llp != pRing->pHead) { + if (pStart == pRing->pHead) { + (*fpPrint) ("Head\n"); + } + if (pStart == pRing->pTail) { + (*fpPrint) ("Tail\n"); + } + if (pStart == pRing->pProg) { + (*fpPrint) ("Prog\n"); + } + if (pStart == pRing->pEnd) { + (*fpPrint) ("End\n"); + } + if (pStart == pRing->pFree) { + (*fpPrint) ("Free\n"); + } + (*fpPrint) ("0x%X:\n", (uint32_t) pStart); + (*fpPrint) ("sar 0x%0X\n", pStart->sar); + (*fpPrint) ("dar 0x%0X\n", pStart->dar); + (*fpPrint) ("llp 0x%0X\n", pStart->llp); + (*fpPrint) ("ctl.lo 0x%0X\n", pStart->ctl.lo); + (*fpPrint) ("ctl.hi 0x%0X\n", pStart->ctl.hi); + (*fpPrint) ("sstat 0x%0X\n", pStart->sstat); + (*fpPrint) ("dstat 0x%0X\n", pStart->dstat); + (*fpPrint) ("devCtl 0x%0X\n", pStart->devCtl); + + pStart = (dmacHw_DESC_t *) pStart->llp; + } + if (pStart == pRing->pHead) { + (*fpPrint) ("Head\n"); + } + if (pStart == pRing->pTail) { + (*fpPrint) ("Tail\n"); + } + if (pStart == pRing->pProg) { + (*fpPrint) ("Prog\n"); + } + if (pStart == pRing->pEnd) { + (*fpPrint) ("End\n"); + } + if (pStart == pRing->pFree) { + (*fpPrint) ("Free\n"); + } + (*fpPrint) ("0x%X:\n", (uint32_t) pStart); + (*fpPrint) ("sar 0x%0X\n", pStart->sar); + (*fpPrint) ("dar 0x%0X\n", pStart->dar); + (*fpPrint) ("llp 0x%0X\n", pStart->llp); + (*fpPrint) ("ctl.lo 0x%0X\n", pStart->ctl.lo); + (*fpPrint) ("ctl.hi 0x%0X\n", pStart->ctl.hi); + (*fpPrint) ("sstat 0x%0X\n", pStart->sstat); + (*fpPrint) ("dstat 0x%0X\n", pStart->dstat); + (*fpPrint) ("devCtl 0x%0X\n", pStart->devCtl); +} + +/****************************************************************************/ +/** +* @brief Check if DMA channel is the flow controller +* +* @return 1 : If DMA is a flow controler +* 0 : Peripheral is the flow controller +* +* @note +* None +*/ +/****************************************************************************/ +static inline int DmaIsFlowController(void *pDescriptor /* [ IN ] Descriptor buffer */ + ) { + uint32_t ttfc = + (dmacHw_GET_DESC_RING(pDescriptor))->pTail->ctl. + lo & dmacHw_REG_CTL_TTFC_MASK; + + switch (ttfc) { + case dmacHw_REG_CTL_TTFC_MM_DMAC: + case dmacHw_REG_CTL_TTFC_MP_DMAC: + case dmacHw_REG_CTL_TTFC_PM_DMAC: + case dmacHw_REG_CTL_TTFC_PP_DMAC: + return 1; + } + + return 0; +} + +/****************************************************************************/ +/** +* @brief Overwrites data length in the descriptor +* +* This function overwrites data length in the descriptor +* +* +* @return void +* +* @note +* This is only used for PCM channel +*/ +/****************************************************************************/ +void dmacHw_setDataLength(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + size_t dataLen /* [ IN ] Data length in bytes */ + ) { + dmacHw_DESC_t *pProg; + dmacHw_DESC_t *pHead; + int srcTs = 0; + int srcTrSize = 0; + + pHead = (dmacHw_GET_DESC_RING(pDescriptor))->pHead; + pProg = pHead; + + srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); + srcTs = dataLen / srcTrSize; + do { + pProg->ctl.hi = srcTs & dmacHw_REG_CTL_BLOCK_TS_MASK; + pProg = (dmacHw_DESC_t *) pProg->llp; + } while (pProg != pHead); +} + +/****************************************************************************/ +/** +* @brief Clears the interrupt +* +* This function clears the DMA channel specific interrupt +* +* +* @return void +* +* @note +* Must be called under the context of ISR +*/ +/****************************************************************************/ +void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); + dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); +} + +/****************************************************************************/ +/** +* @brief Returns the cause of channel specific DMA interrupt +* +* This function returns the cause of interrupt +* +* @return Interrupt status, each bit representing a specific type of interrupt +* +* @note +* Should be called under the context of ISR +*/ +/****************************************************************************/ +dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + dmacHw_INTERRUPT_STATUS_e status = dmacHw_INTERRUPT_STATUS_NONE; + + if (dmacHw_REG_INT_STAT_TRAN(pCblk->module) & + ((0x00000001 << pCblk->channel))) { + status |= dmacHw_INTERRUPT_STATUS_TRANS; + } + if (dmacHw_REG_INT_STAT_BLOCK(pCblk->module) & + ((0x00000001 << pCblk->channel))) { + status |= dmacHw_INTERRUPT_STATUS_BLOCK; + } + if (dmacHw_REG_INT_STAT_ERROR(pCblk->module) & + ((0x00000001 << pCblk->channel))) { + status |= dmacHw_INTERRUPT_STATUS_ERROR; + } + + return status; +} + +/****************************************************************************/ +/** +* @brief Indentifies a DMA channel causing interrupt +* +* This functions returns a channel causing interrupt of type dmacHw_INTERRUPT_STATUS_e +* +* @return NULL : No channel causing DMA interrupt +* ! NULL : Handle to a channel causing DMA interrupt +* @note +* dmacHw_clearInterrupt() must be called with a valid handle after calling this function +*/ +/****************************************************************************/ +dmacHw_HANDLE_t dmacHw_getInterruptSource(void) +{ + uint32_t i; + + for (i = 0; i < dmaChannelCount_0 + dmaChannelCount_1; i++) { + if ((dmacHw_REG_INT_STAT_TRAN(dmacHw_gCblk[i].module) & + ((0x00000001 << dmacHw_gCblk[i].channel))) + || (dmacHw_REG_INT_STAT_BLOCK(dmacHw_gCblk[i].module) & + ((0x00000001 << dmacHw_gCblk[i].channel))) + || (dmacHw_REG_INT_STAT_ERROR(dmacHw_gCblk[i].module) & + ((0x00000001 << dmacHw_gCblk[i].channel))) + ) { + return dmacHw_CBLK_TO_HANDLE(&dmacHw_gCblk[i]); + } + } + return dmacHw_CBLK_TO_HANDLE(NULL); +} + +/****************************************************************************/ +/** +* @brief Estimates number of descriptor needed to perform certain DMA transfer +* +* +* @return On failure : -1 +* On success : Number of descriptor count +* +* +*/ +/****************************************************************************/ +int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pSrcAddr, /* [ IN ] Source (Peripheral/Memory) address */ + void *pDstAddr, /* [ IN ] Destination (Peripheral/Memory) address */ + size_t dataLen /* [ IN ] Data length in bytes */ + ) { + int srcTs = 0; + int oddSize = 0; + int descCount = 0; + int dstTrSize = 0; + int srcTrSize = 0; + uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE; + dmacHw_TRANSACTION_WIDTH_e dstTrWidth; + dmacHw_TRANSACTION_WIDTH_e srcTrWidth; + + dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); + srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); + + /* Skip Tx if buffer is NULL or length is unknown */ + if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) { + /* Do not initiate transfer */ + return -1; + } + + /* Ensure scatter and gather are transaction aligned */ + if (pConfig->srcGatherWidth % srcTrSize + || pConfig->dstScatterWidth % dstTrSize) { + return -1; + } + + /* + Background 1: DMAC can not perform DMA if source and destination addresses are + not properly aligned with the channel's transaction width. So, for successful + DMA transfer, transaction width must be set according to the alignment of the + source and destination address. + */ + + /* Adjust destination transaction width if destination address is not aligned properly */ + dstTrWidth = pConfig->dstMaxTransactionWidth; + while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) { + dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth); + dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth); + } + + /* Adjust source transaction width if source address is not aligned properly */ + srcTrWidth = pConfig->srcMaxTransactionWidth; + while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) { + srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth); + srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth); + } + + /* Find the maximum transaction per descriptor */ + if (pConfig->maxDataPerBlock + && ((pConfig->maxDataPerBlock / srcTrSize) < + dmacHw_MAX_BLOCKSIZE)) { + maxBlockSize = pConfig->maxDataPerBlock / srcTrSize; + } + + /* Find number of source transactions needed to complete the DMA transfer */ + srcTs = dataLen / srcTrSize; + /* Find the odd number of bytes that need to be transferred as single byte transaction width */ + if (srcTs && (dstTrSize > srcTrSize)) { + oddSize = dataLen % dstTrSize; + /* Adjust source transaction count due to "oddSize" */ + srcTs = srcTs - (oddSize / srcTrSize); + } else { + oddSize = dataLen % srcTrSize; + } + /* Adjust "descCount" due to "oddSize" */ + if (oddSize) { + descCount++; + } + + /* Find the number of descriptor needed for total "srcTs" */ + if (srcTs) { + descCount += ((srcTs - 1) / maxBlockSize) + 1; + } + + return descCount; +} + +/****************************************************************************/ +/** +* @brief Check the existance of pending descriptor +* +* This function confirmes if there is any pending descriptor in the chain +* to program the channel +* +* @return 1 : Channel need to be programmed with pending descriptor +* 0 : No more pending descriptor to programe the channel +* +* @note +* - This function should be called from ISR in case there are pending +* descriptor to program the channel. +* +* Example: +* +* dmac_isr () +* { +* ... +* if (dmacHw_descriptorPending (handle)) +* { +* dmacHw_initiateTransfer (handle); +* } +* } +* +*/ +/****************************************************************************/ +uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *pDescriptor /* [ IN ] Descriptor buffer */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + + /* Make sure channel is not busy */ + if (!CHANNEL_BUSY(pCblk->module, pCblk->channel)) { + /* Check if pEnd is not processed */ + if (pRing->pEnd) { + /* Something left for processing */ + return 1; + } + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Program channel register to stop transfer +* +* Ensures the channel is not doing any transfer after calling this function +* +* @return void +* +*/ +/****************************************************************************/ +void dmacHw_stopTransfer(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk; + + pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + /* Stop the channel */ + dmacHw_DMA_STOP(pCblk->module, pCblk->channel); +} + +/****************************************************************************/ +/** +* @brief Deallocates source or destination memory, allocated +* +* This function can be called to deallocate data memory that was DMAed successfully +* +* @return On failure : -1 +* On success : Number of buffer freed +* +* @note +* This function will be called ONLY, when source OR destination address is pointing +* to dynamic memory +*/ +/****************************************************************************/ +int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void (*fpFree) (void *) /* [ IN ] Function pointer to free data memory */ + ) { + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + uint32_t count = 0; + + if (fpFree == NULL) { + return -1; + } + + while ((pRing->pFree != pRing->pTail) + && (pRing->pFree->ctl.lo & dmacHw_DESC_FREE)) { + if (pRing->pFree->devCtl == dmacHw_FREE_USER_MEMORY) { + /* Identify, which memory to free */ + if (dmacHw_DST_IS_MEMORY(pConfig->transferType)) { + (*fpFree) ((void *)pRing->pFree->dar); + } else { + /* Destination was a peripheral */ + (*fpFree) ((void *)pRing->pFree->sar); + } + /* Unmark user memory to indicate it is freed */ + pRing->pFree->devCtl = ~dmacHw_FREE_USER_MEMORY; + } + dmacHw_NEXT_DESC(pRing, pFree); + + count++; + } + + return count; +} + +/****************************************************************************/ +/** +* @brief Prepares descriptor ring, when source peripheral working as a flow controller +* +* This function will update the discriptor ring by allocating buffers, when source peripheral +* has to work as a flow controller to transfer data from: +* - Peripheral to memory. +* +* @return On failure : -1 +* On success : Number of descriptor updated +* +* +* @note +* Channel must be configured for peripheral to memory transfer +* +*/ +/****************************************************************************/ +int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + uint32_t srcAddr, /* [ IN ] Source peripheral address */ + void *(*fpAlloc) (int len), /* [ IN ] Function pointer that provides destination memory */ + int len, /* [ IN ] Number of bytes "fpAlloc" will allocate for destination */ + int num /* [ IN ] Number of descriptor to set */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + dmacHw_DESC_t *pProg = NULL; + dmacHw_DESC_t *pLast = NULL; + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + uint32_t dstAddr; + uint32_t controlParam; + int i; + + dmacHw_ASSERT(pConfig->transferType == + dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM); + + if (num > pRing->num) { + return -1; + } + + pLast = pRing->pEnd; /* Last descriptor updated */ + pProg = pRing->pHead; /* First descriptor in the new list */ + + controlParam = pConfig->srcUpdate | + pConfig->dstUpdate | + pConfig->srcMaxTransactionWidth | + pConfig->dstMaxTransactionWidth | + pConfig->srcMasterInterface | + pConfig->dstMasterInterface | + pConfig->srcMaxBurstWidth | + pConfig->dstMaxBurstWidth | + dmacHw_REG_CTL_TTFC_PM_PERI | + dmacHw_REG_CTL_LLP_DST_EN | + dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN; + + for (i = 0; i < num; i++) { + /* Allocate Rx buffer only for idle descriptor */ + if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) || + ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail) + ) { + /* Rx descriptor is not idle */ + break; + } + /* Set source address */ + pRing->pHead->sar = srcAddr; + if (fpAlloc) { + /* Allocate memory for buffer in descriptor */ + dstAddr = (uint32_t) (*fpAlloc) (len); + /* Check the destination address */ + if (dstAddr == 0) { + if (i == 0) { + /* Not a single descriptor is available */ + return -1; + } + break; + } + /* Set destination address */ + pRing->pHead->dar = dstAddr; + } + /* Set control information */ + pRing->pHead->ctl.lo = controlParam; + /* Use "devCtl" to mark the memory that need to be freed later */ + pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY; + /* Descriptor is now owned by the channel */ + pRing->pHead->ctl.hi = 0; + /* Remember the descriptor last updated */ + pRing->pEnd = pRing->pHead; + /* Update next descriptor */ + dmacHw_NEXT_DESC(pRing, pHead); + } + + /* Mark the end of the list */ + pRing->pEnd->ctl.lo &= + ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN); + /* Connect the list */ + if (pLast != pProg) { + pLast->ctl.lo |= + dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN; + } + /* Mark the descriptors are updated */ + pCblk->descUpdated = 1; + if (!pCblk->varDataStarted) { + /* LLP must be pointing to the first descriptor */ + dmacHw_SET_LLP(pCblk->module, pCblk->channel, + (uint32_t) pProg - pRing->virt2PhyOffset); + /* Channel, handling variable data started */ + pCblk->varDataStarted = 1; + } + + return i; +} + +/****************************************************************************/ +/** +* @brief Read data DMAed to memory +* +* This function will read data that has been DMAed to memory while transfering from: +* - Memory to memory +* - Peripheral to memory +* +* @param handle - +* @param ppBbuf - +* @param pLen - +* +* @return 0 - No more data is available to read +* 1 - More data might be available to read +* +*/ +/****************************************************************************/ +int dmacHw_readTransferredData(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + void **ppBbuf, /* [ OUT ] Data received */ + size_t *pLlen /* [ OUT ] Length of the data received */ + ) { + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + + (void)handle; + + if (pConfig->transferMode != dmacHw_TRANSFER_MODE_CONTINUOUS) { + if (((pRing->pTail->ctl.hi & dmacHw_DESC_FREE) == 0) || + (pRing->pTail == pRing->pHead) + ) { + /* No receive data available */ + *ppBbuf = (char *)NULL; + *pLlen = 0; + + return 0; + } + } + + /* Return read buffer and length */ + *ppBbuf = (char *)pRing->pTail->dar; + + /* Extract length of the received data */ + if (DmaIsFlowController(pDescriptor)) { + uint32_t srcTrSize = 0; + + switch (pRing->pTail->ctl.lo & dmacHw_REG_CTL_SRC_TR_WIDTH_MASK) { + case dmacHw_REG_CTL_SRC_TR_WIDTH_8: + srcTrSize = 1; + break; + case dmacHw_REG_CTL_SRC_TR_WIDTH_16: + srcTrSize = 2; + break; + case dmacHw_REG_CTL_SRC_TR_WIDTH_32: + srcTrSize = 4; + break; + case dmacHw_REG_CTL_SRC_TR_WIDTH_64: + srcTrSize = 8; + break; + default: + dmacHw_ASSERT(0); + } + /* Calculate length from the block size */ + *pLlen = + (pRing->pTail->ctl.hi & dmacHw_REG_CTL_BLOCK_TS_MASK) * + srcTrSize; + } else { + /* Extract length from the source peripheral */ + *pLlen = pRing->pTail->sstat; + } + + /* Advance tail to next descriptor */ + dmacHw_NEXT_DESC(pRing, pTail); + + return 1; +} + +/****************************************************************************/ +/** +* @brief Set descriptor carrying control information +* +* This function will be used to send specific control information to the device +* using the DMA channel +* +* +* @return -1 - On failure +* 0 - On success +* +* @note +* None +*/ +/****************************************************************************/ +int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig, /* [ IN ] Configuration settings */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + uint32_t ctlAddress, /* [ IN ] Address of the device control register */ + uint32_t control /* [ IN ] Device control information */ + ) { + dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); + + if (ctlAddress == 0) { + return -1; + } + + /* Check the availability of descriptors in the ring */ + if ((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) { + return -1; + } + /* Set control information */ + pRing->pHead->devCtl = control; + /* Set source and destination address */ + pRing->pHead->sar = (uint32_t) &pRing->pHead->devCtl; + pRing->pHead->dar = ctlAddress; + /* Set control parameters */ + if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) { + pRing->pHead->ctl.lo = pConfig->transferType | + dmacHw_SRC_ADDRESS_UPDATE_MODE_INC | + dmacHw_DST_ADDRESS_UPDATE_MODE_INC | + dmacHw_SRC_TRANSACTION_WIDTH_32 | + pConfig->dstMaxTransactionWidth | + dmacHw_SRC_BURST_WIDTH_0 | + dmacHw_DST_BURST_WIDTH_0 | + pConfig->srcMasterInterface | + pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN; + } else { + uint32_t transferType = 0; + switch (pConfig->transferType) { + case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: + transferType = dmacHw_REG_CTL_TTFC_PM_PERI; + break; + case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: + transferType = dmacHw_REG_CTL_TTFC_MP_PERI; + break; + default: + dmacHw_ASSERT(0); + } + pRing->pHead->ctl.lo = transferType | + dmacHw_SRC_ADDRESS_UPDATE_MODE_INC | + dmacHw_DST_ADDRESS_UPDATE_MODE_INC | + dmacHw_SRC_TRANSACTION_WIDTH_32 | + pConfig->dstMaxTransactionWidth | + dmacHw_SRC_BURST_WIDTH_0 | + dmacHw_DST_BURST_WIDTH_0 | + pConfig->srcMasterInterface | + pConfig->dstMasterInterface | + pConfig->flowControler | dmacHw_REG_CTL_INT_EN; + } + + /* Set block transaction size to one 32 bit transaction */ + pRing->pHead->ctl.hi = dmacHw_REG_CTL_BLOCK_TS_MASK & 1; + + /* Remember the descriptor to initialize the registers */ + if (pRing->pProg == dmacHw_DESC_INIT) { + pRing->pProg = pRing->pHead; + } + pRing->pEnd = pRing->pHead; + + /* Advance the descriptor */ + dmacHw_NEXT_DESC(pRing, pHead); + + /* Update Tail pointer if destination is a peripheral */ + if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) { + pRing->pTail = pRing->pHead; + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Sets channel specific user data +* +* This function associates user data to a specif DMA channel +* +*/ +/****************************************************************************/ +void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *userData /* [ IN ] User data */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + pCblk->userData = userData; +} + +/****************************************************************************/ +/** +* @brief Gets channel specific user data +* +* This function returns user data specific to a DMA channel +* +* @return user data +*/ +/****************************************************************************/ +void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle /* [ IN ] DMA Channel handle */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + return pCblk->userData; +} + +/****************************************************************************/ +/** +* @brief Resets descriptor control information +* +* @return void +*/ +/****************************************************************************/ +void dmacHw_resetDescriptorControl(void *pDescriptor /* [ IN ] Descriptor buffer */ + ) { + int i; + dmacHw_DESC_RING_t *pRing; + dmacHw_DESC_t *pDesc; + + pRing = dmacHw_GET_DESC_RING(pDescriptor); + pDesc = pRing->pHead; + + for (i = 0; i < pRing->num; i++) { + /* Mark descriptor is ready to use */ + pDesc->ctl.hi = dmacHw_DESC_FREE; + /* Look into next link list item */ + pDesc++; + } + pRing->pFree = pRing->pTail = pRing->pEnd = pRing->pHead; + pRing->pProg = dmacHw_DESC_INIT; +} + +/****************************************************************************/ +/** +* @brief Displays channel specific registers and other control parameters +* +* @return void +* +* +* @note +* None +*/ +/****************************************************************************/ +void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle, /* [ IN ] DMA Channel handle */ + void *pDescriptor, /* [ IN ] Descriptor buffer */ + int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */ + ) { + dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); + + DisplayRegisterContents(pCblk->module, pCblk->channel, fpPrint); + DisplayDescRing(pDescriptor, fpPrint); +} -- GitLab From 7ba09020287fa6c181707490ea7143abb3db55b1 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:09:49 +0100 Subject: [PATCH 0989/1002] ARM: 5660/1: bcmring: add csp timer block header and source files add csp timer block header and source files Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/csp/tmr/Makefile | 1 + arch/arm/mach-bcmring/csp/tmr/tmrHw.c | 576 ++++++++++++++++++ arch/arm/mach-bcmring/include/csp/tmrHw.h | 263 ++++++++ .../mach-bcmring/include/mach/csp/tmrHw_reg.h | 82 +++ 4 files changed, 922 insertions(+) create mode 100644 arch/arm/mach-bcmring/csp/tmr/Makefile create mode 100644 arch/arm/mach-bcmring/csp/tmr/tmrHw.c create mode 100644 arch/arm/mach-bcmring/include/csp/tmrHw.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/tmrHw_reg.h diff --git a/arch/arm/mach-bcmring/csp/tmr/Makefile b/arch/arm/mach-bcmring/csp/tmr/Makefile new file mode 100644 index 0000000000000..244a61ab76973 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/tmr/Makefile @@ -0,0 +1 @@ +obj-y += tmrHw.o diff --git a/arch/arm/mach-bcmring/csp/tmr/tmrHw.c b/arch/arm/mach-bcmring/csp/tmr/tmrHw.c new file mode 100644 index 0000000000000..5c1c9a0e5ed21 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/tmr/tmrHw.c @@ -0,0 +1,576 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file tmrHw.c +* +* @brief Low level Timer driver routines +* +* @note +* +* These routines provide basic timer functionality only. +*/ +/****************************************************************************/ + +/* ---- Include Files ---------------------------------------------------- */ + +#include <csp/errno.h> +#include <csp/stdint.h> + +#include <csp/tmrHw.h> +#include <mach/csp/tmrHw_reg.h> + +#define tmrHw_ASSERT(a) if (!(a)) *(char *)0 = 0 +#define tmrHw_MILLISEC_PER_SEC (1000) + +#define tmrHw_LOW_1_RESOLUTION_COUNT (tmrHw_LOW_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC) +#define tmrHw_LOW_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_1_RESOLUTION_COUNT) +#define tmrHw_LOW_16_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 16) +#define tmrHw_LOW_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_16_RESOLUTION_COUNT) +#define tmrHw_LOW_256_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 256) +#define tmrHw_LOW_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_256_RESOLUTION_COUNT) + +#define tmrHw_HIGH_1_RESOLUTION_COUNT (tmrHw_HIGH_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC) +#define tmrHw_HIGH_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_1_RESOLUTION_COUNT) +#define tmrHw_HIGH_16_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 16) +#define tmrHw_HIGH_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_16_RESOLUTION_COUNT) +#define tmrHw_HIGH_256_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 256) +#define tmrHw_HIGH_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_256_RESOLUTION_COUNT) + +static void ResetTimer(tmrHw_ID_t timerId) + __attribute__ ((section(".aramtext"))); +static int tmrHw_divide(int num, int denom) + __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Get timer capability +* +* This function returns various capabilities/attributes of a timer +* +* @return Capability +* +*/ +/****************************************************************************/ +uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_CAPABILITY_e capability /* [ IN ] Timer capability */ +) { + switch (capability) { + case tmrHw_CAPABILITY_CLOCK: + return (timerId <= + 1) ? tmrHw_LOW_RESOLUTION_CLOCK : + tmrHw_HIGH_RESOLUTION_CLOCK; + case tmrHw_CAPABILITY_RESOLUTION: + return 32; + default: + return 0; + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Resets a timer +* +* This function initializes timer +* +* @return void +* +*/ +/****************************************************************************/ +static void ResetTimer(tmrHw_ID_t timerId /* [ IN ] Timer Id */ +) { + /* Reset timer */ + pTmrHw[timerId].LoadValue = 0; + pTmrHw[timerId].CurrentValue = 0xFFFFFFFF; + pTmrHw[timerId].Control = 0; + pTmrHw[timerId].BackgroundLoad = 0; + /* Always configure as a 32 bit timer */ + pTmrHw[timerId].Control |= tmrHw_CONTROL_32BIT; + /* Clear interrupt only if raw status interrupt is set */ + if (pTmrHw[timerId].RawInterruptStatus) { + pTmrHw[timerId].InterruptClear = 0xFFFFFFFF; + } +} + +/****************************************************************************/ +/** +* @brief Sets counter value for an interval in ms +* +* @return On success: Effective counter value set +* On failure: 0 +* +*/ +/****************************************************************************/ +static tmrHw_INTERVAL_t SetTimerPeriod(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */ +) { + uint32_t scale = 0; + uint32_t count = 0; + + if (timerId == 0 || timerId == 1) { + if (msec <= tmrHw_LOW_1_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1; + scale = tmrHw_LOW_1_RESOLUTION_COUNT; + } else if (msec <= tmrHw_LOW_16_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16; + scale = tmrHw_LOW_16_RESOLUTION_COUNT; + } else if (msec <= tmrHw_LOW_256_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256; + scale = tmrHw_LOW_256_RESOLUTION_COUNT; + } else { + return 0; + } + + count = msec * scale; + /* Set counter value */ + pTmrHw[timerId].LoadValue = count; + pTmrHw[timerId].BackgroundLoad = count; + + } else if (timerId == 2 || timerId == 3) { + if (msec <= tmrHw_HIGH_1_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1; + scale = tmrHw_HIGH_1_RESOLUTION_COUNT; + } else if (msec <= tmrHw_HIGH_16_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16; + scale = tmrHw_HIGH_16_RESOLUTION_COUNT; + } else if (msec <= tmrHw_HIGH_256_MAX_MILLISEC) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256; + scale = tmrHw_HIGH_256_RESOLUTION_COUNT; + } else { + return 0; + } + + count = msec * scale; + /* Set counter value */ + pTmrHw[timerId].LoadValue = count; + pTmrHw[timerId].BackgroundLoad = count; + } + return count / scale; +} + +/****************************************************************************/ +/** +* @brief Configures a periodic timer in terms of timer interrupt rate +* +* This function initializes a periodic timer to generate specific number of +* timer interrupt per second +* +* @return On success: Effective timer frequency +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_RATE_t rate /* [ IN ] Number of timer interrupt per second */ +) { + uint32_t resolution = 0; + uint32_t count = 0; + ResetTimer(timerId); + + /* Set timer mode periodic */ + pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC; + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT; + /* Set timer in highest resolution */ + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1; + + if (rate && (timerId == 0 || timerId == 1)) { + if (rate > tmrHw_LOW_RESOLUTION_CLOCK) { + return 0; + } + resolution = tmrHw_LOW_RESOLUTION_CLOCK; + } else if (rate && (timerId == 2 || timerId == 3)) { + if (rate > tmrHw_HIGH_RESOLUTION_CLOCK) { + return 0; + } else { + resolution = tmrHw_HIGH_RESOLUTION_CLOCK; + } + } else { + return 0; + } + /* Find the counter value */ + count = resolution / rate; + /* Set counter value */ + pTmrHw[timerId].LoadValue = count; + pTmrHw[timerId].BackgroundLoad = count; + + return resolution / count; +} + +/****************************************************************************/ +/** +* @brief Configures a periodic timer to generate timer interrupt after +* certain time interval +* +* This function initializes a periodic timer to generate timer interrupt +* after every time interval in millisecond +* +* @return On success: Effective interval set in milli-second +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */ +) { + ResetTimer(timerId); + + /* Set timer mode periodic */ + pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC; + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT; + + return SetTimerPeriod(timerId, msec); +} + +/****************************************************************************/ +/** +* @brief Configures a periodic timer to generate timer interrupt just once +* after certain time interval +* +* This function initializes a periodic timer to generate a single ticks after +* certain time interval in millisecond +* +* @return On success: Effective interval set in milli-second +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_INTERVAL_t msec /* [ IN ] Interval in milli-second */ +) { + ResetTimer(timerId); + + /* Set timer mode oneshot */ + pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC; + pTmrHw[timerId].Control |= tmrHw_CONTROL_ONESHOT; + + return SetTimerPeriod(timerId, msec); +} + +/****************************************************************************/ +/** +* @brief Configures a timer to run as a free running timer +* +* This function initializes a timer to run as a free running timer +* +* @return Timer resolution (count / sec) +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + uint32_t divider /* [ IN ] Dividing the clock frequency */ +) { + uint32_t scale = 0; + + ResetTimer(timerId); + /* Set timer as free running mode */ + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_PERIODIC; + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT; + + if (divider >= 64) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256; + scale = 256; + } else if (divider >= 8) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16; + scale = 16; + } else { + pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1; + scale = 1; + } + + if (timerId == 0 || timerId == 1) { + return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, scale); + } else if (timerId == 2 || timerId == 3) { + return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, scale); + } + + return 0; +} + +/****************************************************************************/ +/** +* @brief Starts a timer +* +* This function starts a preconfigured timer +* +* @return -1 - On Failure +* 0 - On Success +* +*/ +/****************************************************************************/ +int tmrHw_startTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_TIMER_ENABLE; + return 0; +} + +/****************************************************************************/ +/** +* @brief Stops a timer +* +* This function stops a running timer +* +* @return -1 - On Failure +* 0 - On Success +* +*/ +/****************************************************************************/ +int tmrHw_stopTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_TIMER_ENABLE; + return 0; +} + +/****************************************************************************/ +/** +* @brief Gets current timer count +* +* This function returns the current timer value +* +* @return Current downcounting timer value +* +*/ +/****************************************************************************/ +uint32_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + /* return 32 bit timer value */ + switch (pTmrHw[timerId].Control & tmrHw_CONTROL_MODE_MASK) { + case tmrHw_CONTROL_FREE_RUNNING: + if (pTmrHw[timerId].CurrentValue) { + return tmrHw_MAX_COUNT - pTmrHw[timerId].CurrentValue; + } + break; + case tmrHw_CONTROL_PERIODIC: + case tmrHw_CONTROL_ONESHOT: + return pTmrHw[timerId].BackgroundLoad - + pTmrHw[timerId].CurrentValue; + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Gets timer count rate +* +* This function returns the number of counts per second +* +* @return Count rate +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + uint32_t divider = 0; + + switch (pTmrHw[timerId].Control & tmrHw_CONTROL_PRESCALE_MASK) { + case tmrHw_CONTROL_PRESCALE_1: + divider = 1; + break; + case tmrHw_CONTROL_PRESCALE_16: + divider = 16; + break; + case tmrHw_CONTROL_PRESCALE_256: + divider = 256; + break; + default: + tmrHw_ASSERT(0); + } + + if (timerId == 0 || timerId == 1) { + return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, divider); + } else { + return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, divider); + } + return 0; +} + +/****************************************************************************/ +/** +* @brief Enables timer interrupt +* +* This function enables the timer interrupt +* +* @return N/A +* +*/ +/****************************************************************************/ +void tmrHw_enableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + pTmrHw[timerId].Control |= tmrHw_CONTROL_INTERRUPT_ENABLE; +} + +/****************************************************************************/ +/** +* @brief Disables timer interrupt +* +* This function disable the timer interrupt +* +* @return N/A +* +*/ +/****************************************************************************/ +void tmrHw_disableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + pTmrHw[timerId].Control &= ~tmrHw_CONTROL_INTERRUPT_ENABLE; +} + +/****************************************************************************/ +/** +* @brief Clears the interrupt +* +* This function clears the timer interrupt +* +* @return N/A +* +* @note +* Must be called under the context of ISR +*/ +/****************************************************************************/ +void tmrHw_clearInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + pTmrHw[timerId].InterruptClear = 0x1; +} + +/****************************************************************************/ +/** +* @brief Gets the interrupt status +* +* This function returns timer interrupt status +* +* @return Interrupt status +*/ +/****************************************************************************/ +tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) { + if (pTmrHw[timerId].InterruptStatus) { + return tmrHw_INTERRUPT_STATUS_SET; + } else { + return tmrHw_INTERRUPT_STATUS_UNSET; + } +} + +/****************************************************************************/ +/** +* @brief Indentifies a timer causing interrupt +* +* This functions returns a timer causing interrupt +* +* @return 0xFFFFFFFF : No timer causing an interrupt +* ! 0xFFFFFFFF : timer causing an interrupt +* @note +* tmrHw_clearIntrrupt() must be called with a valid timer id after calling this function +*/ +/****************************************************************************/ +tmrHw_ID_t tmrHw_getInterruptSource(void /* void */ +) { + int i; + + for (i = 0; i < tmrHw_TIMER_NUM_COUNT; i++) { + if (pTmrHw[i].InterruptStatus) { + return i; + } + } + + return 0xFFFFFFFF; +} + +/****************************************************************************/ +/** +* @brief Displays specific timer registers +* +* +* @return void +* +*/ +/****************************************************************************/ +void tmrHw_printDebugInfo(tmrHw_ID_t timerId, /* [ IN ] Timer id */ + int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */ +) { + (*fpPrint) ("Displaying register contents \n\n"); + (*fpPrint) ("Timer %d: Load value 0x%X\n", timerId, + pTmrHw[timerId].LoadValue); + (*fpPrint) ("Timer %d: Background load value 0x%X\n", timerId, + pTmrHw[timerId].BackgroundLoad); + (*fpPrint) ("Timer %d: Control 0x%X\n", timerId, + pTmrHw[timerId].Control); + (*fpPrint) ("Timer %d: Interrupt clear 0x%X\n", timerId, + pTmrHw[timerId].InterruptClear); + (*fpPrint) ("Timer %d: Interrupt raw interrupt 0x%X\n", timerId, + pTmrHw[timerId].RawInterruptStatus); + (*fpPrint) ("Timer %d: Interrupt status 0x%X\n", timerId, + pTmrHw[timerId].InterruptStatus); +} + +/****************************************************************************/ +/** +* @brief Use a timer to perform a busy wait delay for a number of usecs. +* +* @return N/A +*/ +/****************************************************************************/ +void tmrHw_udelay(tmrHw_ID_t timerId, /* [ IN ] Timer id */ + unsigned long usecs /* [ IN ] usec to delay */ +) { + tmrHw_RATE_t usec_tick_rate; + tmrHw_COUNT_t start_time; + tmrHw_COUNT_t delta_time; + + start_time = tmrHw_GetCurrentCount(timerId); + usec_tick_rate = tmrHw_divide(tmrHw_getCountRate(timerId), 1000000); + delta_time = usecs * usec_tick_rate; + + /* Busy wait */ + while (delta_time > (tmrHw_GetCurrentCount(timerId) - start_time)) + ; +} + +/****************************************************************************/ +/** +* @brief Local Divide function +* +* This function does the divide +* +* @return divide value +* +*/ +/****************************************************************************/ +static int tmrHw_divide(int num, int denom) +{ + int r; + int t = 1; + + /* Shift denom and t up to the largest value to optimize algorithm */ + /* t contains the units of each divide */ + while ((denom & 0x40000000) == 0) { /* fails if denom=0 */ + denom = denom << 1; + t = t << 1; + } + + /* Intialize the result */ + r = 0; + + do { + /* Determine if there exists a positive remainder */ + if ((num - denom) >= 0) { + /* Accumlate t to the result and calculate a new remainder */ + num = num - denom; + r = r + t; + } + /* Continue to shift denom and shift t down to 0 */ + denom = denom >> 1; + t = t >> 1; + } while (t != 0); + return r; +} diff --git a/arch/arm/mach-bcmring/include/csp/tmrHw.h b/arch/arm/mach-bcmring/include/csp/tmrHw.h new file mode 100644 index 0000000000000..f1236d00cb976 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/tmrHw.h @@ -0,0 +1,263 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file tmrHw.h +* +* @brief API definitions for low level Timer driver +* +*/ +/****************************************************************************/ +#ifndef _TMRHW_H +#define _TMRHW_H + +#include <csp/stdint.h> + +typedef uint32_t tmrHw_ID_t; /* Timer ID */ +typedef uint32_t tmrHw_COUNT_t; /* Timer count */ +typedef uint32_t tmrHw_INTERVAL_t; /* Timer interval */ +typedef uint32_t tmrHw_RATE_t; /* Timer event (count/interrupt) rate */ + +typedef enum { + tmrHw_INTERRUPT_STATUS_SET, /* Interrupted */ + tmrHw_INTERRUPT_STATUS_UNSET /* No Interrupt */ +} tmrHw_INTERRUPT_STATUS_e; + +typedef enum { + tmrHw_CAPABILITY_CLOCK, /* Clock speed in HHz */ + tmrHw_CAPABILITY_RESOLUTION /* Timer resolution in bits */ +} tmrHw_CAPABILITY_e; + +/****************************************************************************/ +/** +* @brief Get timer capability +* +* This function returns various capabilities/attributes of a timer +* +* @return Numeric capability +* +*/ +/****************************************************************************/ +uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_CAPABILITY_e capability /* [ IN ] Timer capability */ +); + +/****************************************************************************/ +/** +* @brief Configures a periodic timer in terms of timer interrupt rate +* +* This function initializes a periodic timer to generate specific number of +* timer interrupt per second +* +* @return On success: Effective timer frequency +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_RATE_t rate /* [ IN ] Number of timer interrupt per second */ +); + +/****************************************************************************/ +/** +* @brief Configures a periodic timer to generate timer interrupt after +* certain time interval +* +* This function initializes a periodic timer to generate timer interrupt +* after every time interval in milisecond +* +* @return On success: Effective interval set in mili-second +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_INTERVAL_t msec /* [ IN ] Interval in mili-second */ +); + +/****************************************************************************/ +/** +* @brief Configures a periodic timer to generate timer interrupt just once +* after certain time interval +* +* This function initializes a periodic timer to generate a single ticks after +* certain time interval in milisecond +* +* @return On success: Effective interval set in mili-second +* On failure: 0 +* +*/ +/****************************************************************************/ +tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + tmrHw_INTERVAL_t msec /* [ IN ] Interval in mili-second */ +); + +/****************************************************************************/ +/** +* @brief Configures a timer to run as a free running timer +* +* This function initializes a timer to run as a free running timer +* +* @return Timer resolution (count / sec) +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId, /* [ IN ] Timer Id */ + uint32_t divider /* [ IN ] Dividing the clock frequency */ +) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Starts a timer +* +* This function starts a preconfigured timer +* +* @return -1 - On Failure +* 0 - On Success +*/ +/****************************************************************************/ +int tmrHw_startTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Stops a timer +* +* This function stops a running timer +* +* @return -1 - On Failure +* 0 - On Success +*/ +/****************************************************************************/ +int tmrHw_stopTimer(tmrHw_ID_t timerId /* [ IN ] Timer id */ +); + +/****************************************************************************/ +/** +* @brief Gets current timer count +* +* This function returns the current timer value +* +* @return Current downcounting timer value +* +*/ +/****************************************************************************/ +tmrHw_COUNT_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Gets timer count rate +* +* This function returns the number of counts per second +* +* @return Count rate +* +*/ +/****************************************************************************/ +tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId /* [ IN ] Timer id */ +) __attribute__ ((section(".aramtext"))); + +/****************************************************************************/ +/** +* @brief Enables timer interrupt +* +* This function enables the timer interrupt +* +* @return N/A +* +*/ +/****************************************************************************/ +void tmrHw_enableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +); + +/****************************************************************************/ +/** +* @brief Disables timer interrupt +* +* This function disable the timer interrupt +* +* @return N/A +*/ +/****************************************************************************/ +void tmrHw_disableInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +); + +/****************************************************************************/ +/** +* @brief Clears the interrupt +* +* This function clears the timer interrupt +* +* @return N/A +* +* @note +* Must be called under the context of ISR +*/ +/****************************************************************************/ +void tmrHw_clearInterrupt(tmrHw_ID_t timerId /* [ IN ] Timer id */ +); + +/****************************************************************************/ +/** +* @brief Gets the interrupt status +* +* This function returns timer interrupt status +* +* @return Interrupt status +*/ +/****************************************************************************/ +tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId /* [ IN ] Timer id */ +); + +/****************************************************************************/ +/** +* @brief Indentifies a timer causing interrupt +* +* This functions returns a timer causing interrupt +* +* @return 0xFFFFFFFF : No timer causing an interrupt +* ! 0xFFFFFFFF : timer causing an interrupt +* @note +* tmrHw_clearIntrrupt() must be called with a valid timer id after calling this function +*/ +/****************************************************************************/ +tmrHw_ID_t tmrHw_getInterruptSource(void); + +/****************************************************************************/ +/** +* @brief Displays specific timer registers +* +* +* @return void +* +*/ +/****************************************************************************/ +void tmrHw_printDebugInfo(tmrHw_ID_t timerId, /* [ IN ] Timer id */ + int (*fpPrint) (const char *, ...) /* [ IN ] Print callback function */ +); + +/****************************************************************************/ +/** +* @brief Use a timer to perform a busy wait delay for a number of usecs. +* +* @return N/A +*/ +/****************************************************************************/ +void tmrHw_udelay(tmrHw_ID_t timerId, /* [ IN ] Timer id */ + unsigned long usecs /* [ IN ] usec to delay */ +) __attribute__ ((section(".aramtext"))); + +#endif /* _TMRHW_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/tmrHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/tmrHw_reg.h new file mode 100644 index 0000000000000..3080ac7239a10 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/tmrHw_reg.h @@ -0,0 +1,82 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file tmrHw_reg.h +* +* @brief Definitions for low level Timer registers +* +*/ +/****************************************************************************/ +#ifndef _TMRHW_REG_H +#define _TMRHW_REG_H + +#include <mach/csp/mm_io.h> +#include <mach/csp/hw_cfg.h> +/* Base address */ +#define tmrHw_MODULE_BASE_ADDR MM_IO_BASE_TMR + +/* +This platform has four different timers running at different clock speed + +Timer one (Timer ID 0) runs at 25 MHz +Timer two (Timer ID 1) runs at 25 MHz +Timer three (Timer ID 2) runs at 150 MHz +Timer four (Timer ID 3) runs at 150 MHz +*/ +#define tmrHw_LOW_FREQUENCY_MHZ 25 /* Always 25MHz from XTAL */ +#define tmrHw_LOW_FREQUENCY_HZ 25000000 + +#if defined(CFG_GLOBAL_CHIP) && (CFG_GLOBAL_CHIP == FPGA11107) +#define tmrHw_HIGH_FREQUENCY_MHZ 150 /* Always 150MHz for FPGA */ +#define tmrHw_HIGH_FREQUENCY_HZ 150000000 +#else +#define tmrHw_HIGH_FREQUENCY_HZ HW_CFG_BUS_CLK_HZ +#define tmrHw_HIGH_FREQUENCY_MHZ (HW_CFG_BUS_CLK_HZ / 1000000) +#endif + +#define tmrHw_LOW_RESOLUTION_CLOCK tmrHw_LOW_FREQUENCY_HZ +#define tmrHw_HIGH_RESOLUTION_CLOCK tmrHw_HIGH_FREQUENCY_HZ +#define tmrHw_MAX_COUNT (0xFFFFFFFF) /* maximum number of count a timer can count */ +#define tmrHw_TIMER_NUM_COUNT (4) /* Number of timer module supported */ + +typedef struct { + uint32_t LoadValue; /* Load value for timer */ + uint32_t CurrentValue; /* Current value for timer */ + uint32_t Control; /* Control register */ + uint32_t InterruptClear; /* Interrupt clear register */ + uint32_t RawInterruptStatus; /* Raw interrupt status */ + uint32_t InterruptStatus; /* Masked interrupt status */ + uint32_t BackgroundLoad; /* Background load value */ + uint32_t padding; /* Padding register */ +} tmrHw_REG_t; + +/* Control bot masks */ +#define tmrHw_CONTROL_TIMER_ENABLE 0x00000080 +#define tmrHw_CONTROL_PERIODIC 0x00000040 +#define tmrHw_CONTROL_INTERRUPT_ENABLE 0x00000020 +#define tmrHw_CONTROL_PRESCALE_MASK 0x0000000C +#define tmrHw_CONTROL_PRESCALE_1 0x00000000 +#define tmrHw_CONTROL_PRESCALE_16 0x00000004 +#define tmrHw_CONTROL_PRESCALE_256 0x00000008 +#define tmrHw_CONTROL_32BIT 0x00000002 +#define tmrHw_CONTROL_ONESHOT 0x00000001 +#define tmrHw_CONTROL_FREE_RUNNING 0x00000000 + +#define tmrHw_CONTROL_MODE_MASK (tmrHw_CONTROL_PERIODIC | tmrHw_CONTROL_ONESHOT) + +#define pTmrHw ((volatile tmrHw_REG_t *)tmrHw_MODULE_BASE_ADDR) + +#endif /* _TMRHW_REG_H */ -- GitLab From a364143127a3155153f3e93d47cfc0f99a6f1858 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:10:24 +0100 Subject: [PATCH 0990/1002] ARM: 5661/1: bcmring: add csp security hardware headers add csp security hardware headers Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/include/csp/secHw.h | 65 ++++++++++++ .../mach-bcmring/include/mach/csp/secHw_def.h | 100 ++++++++++++++++++ .../include/mach/csp/secHw_inline.h | 79 ++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 arch/arm/mach-bcmring/include/csp/secHw.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/secHw_def.h create mode 100644 arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h diff --git a/arch/arm/mach-bcmring/include/csp/secHw.h b/arch/arm/mach-bcmring/include/csp/secHw.h new file mode 100644 index 0000000000000..b9d7e0732dfc2 --- /dev/null +++ b/arch/arm/mach-bcmring/include/csp/secHw.h @@ -0,0 +1,65 @@ +/***************************************************************************** +* Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file secHw.h +* +* @brief Definitions for accessing low level security features +* +*/ +/****************************************************************************/ +#ifndef SECHW_H +#define SECHW_H + +typedef void (*secHw_FUNC_t) (void); + +typedef enum { + secHw_MODE_SECURE = 0x0, /* Switches processor into secure mode */ + secHw_MODE_NONSECURE = 0x1 /* Switches processor into non-secure mode */ +} secHw_MODE; + +/****************************************************************************/ +/** +* @brief Requesting to execute the function in secure mode +* +* This function requests the given function to run in secure mode +* +*/ +/****************************************************************************/ +void secHw_RunSecure(secHw_FUNC_t /* Function to run in secure mode */ + ); + +/****************************************************************************/ +/** +* @brief Sets the mode +* +* his function sets the processor mode (secure/non-secure) +* +*/ +/****************************************************************************/ +void secHw_SetMode(secHw_MODE /* Processor mode */ + ); + +/****************************************************************************/ +/** +* @brief Get the current mode +* +* This function retieves the processor mode (secure/non-secure) +* +*/ +/****************************************************************************/ +void secHw_GetMode(secHw_MODE *); + +#endif /* SECHW_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/secHw_def.h b/arch/arm/mach-bcmring/include/mach/csp/secHw_def.h new file mode 100644 index 0000000000000..d15f5f3ec2d8d --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/secHw_def.h @@ -0,0 +1,100 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file secHw_def.h +* +* @brief Definitions for configuring/testing secure blocks +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef SECHW_DEF_H +#define SECHW_DEF_H + +#include <mach/csp/mm_io.h> + +/* Bit mask for various secure device */ +#define secHw_BLK_MASK_CHIP_CONTROL 0x00000001 +#define secHw_BLK_MASK_KEY_SCAN 0x00000002 +#define secHw_BLK_MASK_TOUCH_SCREEN 0x00000004 +#define secHw_BLK_MASK_UART0 0x00000008 +#define secHw_BLK_MASK_UART1 0x00000010 +#define secHw_BLK_MASK_WATCHDOG 0x00000020 +#define secHw_BLK_MASK_SPUM 0x00000040 +#define secHw_BLK_MASK_DDR2 0x00000080 +#define secHw_BLK_MASK_EXT_MEM 0x00000100 +#define secHw_BLK_MASK_ESW 0x00000200 +#define secHw_BLK_MASK_SPU 0x00010000 +#define secHw_BLK_MASK_PKA 0x00020000 +#define secHw_BLK_MASK_RNG 0x00040000 +#define secHw_BLK_MASK_RTC 0x00080000 +#define secHw_BLK_MASK_OTP 0x00100000 +#define secHw_BLK_MASK_BOOT 0x00200000 +#define secHw_BLK_MASK_MPU 0x00400000 +#define secHw_BLK_MASK_TZCTRL 0x00800000 +#define secHw_BLK_MASK_INTR 0x01000000 + +/* Trustzone register set */ +typedef struct { + volatile uint32_t status; /* read only - reflects status of writes of 2 write registers */ + volatile uint32_t setUnsecure; /* write only. reads back as 0 */ + volatile uint32_t setSecure; /* write only. reads back as 0 */ +} secHw_TZREG_t; + +/* There are 2 register sets. The first is for the lower 16 bits, the 2nd */ +/* is for the higher 16 bits. */ + +typedef enum { + secHw_IDX_LS = 0, + secHw_IDX_MS = 1, + secHw_IDX_NUM +} secHw_IDX_e; + +typedef struct { + volatile secHw_TZREG_t reg[secHw_IDX_NUM]; +} secHw_REGS_t; + +/****************************************************************************/ +/** +* @brief Configures a device as a secure device +* +*/ +/****************************************************************************/ +static inline void secHw_setSecure(uint32_t mask /* mask of type secHw_BLK_MASK_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Configures a device as a non-secure device +* +*/ +/****************************************************************************/ +static inline void secHw_setUnsecure(uint32_t mask /* mask of type secHw_BLK_MASK_XXXXXX */ + ); + +/****************************************************************************/ +/** +* @brief Get the trustzone status for all components. 1 = non-secure, 0 = secure +* +*/ +/****************************************************************************/ +static inline uint32_t secHw_getStatus(void); + +#include <mach/csp/secHw_inline.h> + +#endif /* SECHW_DEF_H */ diff --git a/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h b/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h new file mode 100644 index 0000000000000..9cd6a032ab716 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h @@ -0,0 +1,79 @@ +/***************************************************************************** +* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +/****************************************************************************/ +/** +* @file secHw_inline.h +* +* @brief Definitions for configuring/testing secure blocks +* +* @note +* None +*/ +/****************************************************************************/ + +#ifndef SECHW_INLINE_H +#define SECHW_INLINE_H + +/****************************************************************************/ +/** +* @brief Configures a device as a secure device +* +*/ +/****************************************************************************/ +static inline void secHw_setSecure(uint32_t mask /* mask of type secHw_BLK_MASK_XXXXXX */ + ) { + secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC; + + if (mask & 0x0000FFFF) { + regp->reg[secHw_IDX_LS].setSecure = mask & 0x0000FFFF; + } + + if (mask & 0xFFFF0000) { + regp->reg[secHw_IDX_MS].setSecure = mask >> 16; + } +} + +/****************************************************************************/ +/** +* @brief Configures a device as a non-secure device +* +*/ +/****************************************************************************/ +static inline void secHw_setUnsecure(uint32_t mask /* mask of type secHw_BLK_MASK_XXXXXX */ + ) { + secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC; + + if (mask & 0x0000FFFF) { + regp->reg[secHw_IDX_LS].setUnsecure = mask & 0x0000FFFF; + } + if (mask & 0xFFFF0000) { + regp->reg[secHw_IDX_MS].setUnsecure = mask >> 16; + } +} + +/****************************************************************************/ +/** +* @brief Get the trustzone status for all components. 1 = non-secure, 0 = secure +* +*/ +/****************************************************************************/ +static inline uint32_t secHw_getStatus(void) +{ + secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC; + + return (regp->reg[1].status << 16) + regp->reg[0].status; +} + +#endif /* SECHW_INLINE_H */ -- GitLab From bc5739005f9c0585d21c78f61e9d7965f97b2109 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 20:04:17 +0100 Subject: [PATCH 0991/1002] ARM: 5653/1: bcmring: add Makefile of csp code add Makefile of csp code Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/csp/Makefile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm/mach-bcmring/csp/Makefile diff --git a/arch/arm/mach-bcmring/csp/Makefile b/arch/arm/mach-bcmring/csp/Makefile new file mode 100644 index 0000000000000..648c0377530e5 --- /dev/null +++ b/arch/arm/mach-bcmring/csp/Makefile @@ -0,0 +1,3 @@ +obj-y += dmac/ +obj-y += tmr/ +obj-y += chipc/ -- GitLab From 831f1f73a6e1a0a02a5eaa2da5f49cf09c7bb1af Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:46:49 +0100 Subject: [PATCH 0992/1002] ARM: 5642/1: bcmring: add Makefile/Kconfig/Makefile.boot in mach-bcmring add arch/arm/mach-bcmring directory add Kconfig, Makefile, and Makefile.boot in mach-bcmring Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-bcmring/Kconfig | 21 +++++++++++++++++++++ arch/arm/mach-bcmring/Makefile | 8 ++++++++ arch/arm/mach-bcmring/Makefile.boot | 6 ++++++ 3 files changed, 35 insertions(+) create mode 100644 arch/arm/mach-bcmring/Kconfig create mode 100644 arch/arm/mach-bcmring/Makefile create mode 100644 arch/arm/mach-bcmring/Makefile.boot diff --git a/arch/arm/mach-bcmring/Kconfig b/arch/arm/mach-bcmring/Kconfig new file mode 100644 index 0000000000000..457b4384913e4 --- /dev/null +++ b/arch/arm/mach-bcmring/Kconfig @@ -0,0 +1,21 @@ +choice + prompt "Processor selection in BCMRING family of devices" + depends on ARCH_BCMRING + default ARCH_BCM11107 + +config ARCH_FPGA11107 + bool "FPGA11107" + +config ARCH_BCM11107 + bool "BCM11107" +endchoice + +menu "BCMRING Options" + depends on ARCH_BCMRING + +config BCM_ZRELADDR + hex "Compressed ZREL ADDR" + +endmenu + +# source "drivers/char/bcmring/Kconfig" diff --git a/arch/arm/mach-bcmring/Makefile b/arch/arm/mach-bcmring/Makefile new file mode 100644 index 0000000000000..f8d9fcedf9174 --- /dev/null +++ b/arch/arm/mach-bcmring/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := arch.o mm.o irq.o clock.o core.o timer.o dma.o +obj-y += csp/ diff --git a/arch/arm/mach-bcmring/Makefile.boot b/arch/arm/mach-bcmring/Makefile.boot new file mode 100644 index 0000000000000..fb53b283bebb3 --- /dev/null +++ b/arch/arm/mach-bcmring/Makefile.boot @@ -0,0 +1,6 @@ +# Address where decompressor will be written and eventually executed. +# +# default to SDRAM +zreladdr-y := $(CONFIG_BCM_ZRELADDR) +params_phys-y := 0x00000800 + -- GitLab From 6288e28dce9bae24068b7341ebd72a7d176a3539 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Fri, 7 Aug 2009 19:46:15 +0100 Subject: [PATCH 0993/1002] ARM: 5641/1: bcmring: add Kconfig and Makefile entries in arch/arm add bcmring option in Kconfig and add entry in Makefile in arch/arm directory Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/Kconfig | 14 ++++++++++++++ arch/arm/Makefile | 1 + 2 files changed, 15 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index aef63c8e3d2dc..c6d2b19887572 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -637,6 +637,18 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1 and OMAP2). +config ARCH_BCMRING + bool "Broadcom BCMRING" + depends on MMU + select CPU_V6 + select ARM_AMBA + select COMMON_CLKDEV + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select ARCH_WANT_OPTIONAL_GPIOLIB + help + Support for Broadcom's BCMRing platform. + endchoice source "arch/arm/mach-clps711x/Kconfig" @@ -730,6 +742,8 @@ source "arch/arm/mach-u300/Kconfig" source "arch/arm/mach-w90x900/Kconfig" +source "arch/arm/mach-bcmring/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c877d6df23d11..b9ae98b88a7e3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -112,6 +112,7 @@ endif # by CONFIG_* macro name. machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 machine-$(CONFIG_ARCH_AT91) := at91 +machine-$(CONFIG_ARCH_BCMRING) := bcmring machine-$(CONFIG_ARCH_CLPS711X) := clps711x machine-$(CONFIG_ARCH_DAVINCI) := davinci machine-$(CONFIG_ARCH_EBSA110) := ebsa110 -- GitLab From 7f33527f547161f5ddc05c252c81617b8de93f21 Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Wed, 12 Aug 2009 22:07:26 +0100 Subject: [PATCH 0994/1002] ARM: 5670/1: bcmring: add default configuration for bcmring arch add default configuration for bcmring arch Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/configs/bcmring_defconfig | 725 +++++++++++++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 arch/arm/configs/bcmring_defconfig diff --git a/arch/arm/configs/bcmring_defconfig b/arch/arm/configs/bcmring_defconfig new file mode 100644 index 0000000000000..bcc0bac551a58 --- /dev/null +++ b/arch/arm/configs/bcmring_defconfig @@ -0,0 +1,725 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.31-rc3 +# Fri Jul 17 12:07:28 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +# CONFIG_EVENTFD is not set +CONFIG_SHMEM=y +# CONFIG_AIO is not set + +# +# Performance Counters +# +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +CONFIG_ARCH_BCMRING=y +# CONFIG_ARCH_FPGA11107 is not set +CONFIG_ARCH_BCM11107=y + +# +# BCMRING Options +# +CONFIG_BCM_ZRELADDR=0x8000 + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_V6=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_ARM_ERRATA_411920 is not set +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +CONFIG_UACCESS_WITH_MEMCPY=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0e000000 +CONFIG_ZBOOT_ROM_BSS=0x0ea00000 +CONFIG_ZBOOT_ROM=y +CONFIG_CMDLINE="" +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +# CONFIG_NET_KEY is not set +# CONFIG_INET is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +# CONFIG_MTD_CFI_I2 is not set +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_BCM_UMI=y +CONFIG_MTD_NAND_BCM_UMI_HWCS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_NETDEVICES is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_CONSOLE_TRANSLATIONS is not set +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=64 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +# CONFIG_GPIOLIB is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_FILE_LOCKING is not set +# CONFIG_FSNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +# CONFIG_JFFS2_FS_SECURITY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +CONFIG_HEADERS_CHECK=y +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_BUILD_DOCSRC is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y -- GitLab From 57a473f2f97cf3bca78df08aac2f438ddef03bee Mon Sep 17 00:00:00 2001 From: Leo Chen <leochen@broadcom.com> Date: Wed, 12 Aug 2009 22:08:48 +0100 Subject: [PATCH 0995/1002] ARM: 5671/1: bcmring: add maintainer entry add maintainer entry Signed-off-by: Leo Chen <leochen@broadcom.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- MAINTAINERS | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fa2a16def17af..a67a99857e2a7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -603,6 +603,23 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://maxim.org.za/at91_26.html S: Maintained +ARM/BCMRING ARM ARCHITECTURE +P: Leo Chen <leochen@broadcom.com> +P: Scott Branden <sbranden@broadcom.com> +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +S: Maintained +F: arch/arm/mach-bcmring + +ARM/BCMRING MTD NAND DRIVER +P: Leo Chen <leochen@broadcom.com> +P: Scott Branden <sbranden@broadcom.com> +L: linux-mtd@lists.infradead.org +S: Maintained +F: drivers/mtd/nand/bcm_umi_nand.c +F: drivers/mtd/nand/bcm_umi_bch.c +F: drivers/mtd/nand/bcm_umi_hamming.c +F: drivers/mtd/nand/nand_bcm_umi.h + ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE P: Lennert Buytenhek M: kernel@wantstofly.org -- GitLab From 65cec8e3db606608fd1f8dfc4a1c7c37bfba9173 Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Mon, 17 Aug 2009 20:02:06 +0100 Subject: [PATCH 0996/1002] ARM: implement highpte Add the ARM implementation of highpte, which allows PTE tables to be placed in highmem. Unfortunately, we do not offer highpte support when support for L2 cache is enabled. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/Kconfig | 5 +++++ arch/arm/include/asm/pgalloc.h | 16 ++++++++++++---- arch/arm/include/asm/pgtable.h | 17 +++++++++++++---- arch/arm/mm/fault.c | 1 + 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index aef63c8e3d2dc..370f477871227 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1054,6 +1054,11 @@ config HIGHMEM If unsure, say n. +config HIGHPTE + bool "Allocate 2nd-level pagetables from highmem" + depends on HIGHMEM + depends on !OUTER_CACHE + source "mm/Kconfig" config LEDS diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 3dcd64bf18241..b12cc98bbe044 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -36,6 +36,8 @@ extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd); #define pgd_alloc(mm) get_pgd_slow(mm) #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) +#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) + /* * Allocate one PTE table. * @@ -57,7 +59,7 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) { pte_t *pte; - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); + pte = (pte_t *)__get_free_page(PGALLOC_GFP); if (pte) { clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); pte += PTRS_PER_PTE; @@ -71,10 +73,16 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) { struct page *pte; - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); +#ifdef CONFIG_HIGHPTE + pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0); +#else + pte = alloc_pages(PGALLOC_GFP, 0); +#endif if (pte) { - void *page = page_address(pte); - clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); + if (!PageHighMem(pte)) { + void *page = page_address(pte); + clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); + } pgtable_page_ctor(pte); } diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9655bce3d3452..201ccaa11f61b 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -262,10 +262,19 @@ extern struct page *empty_zero_page; #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_offset_map(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_offset_map_nested(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) + +#define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) +#define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) +#define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) +#define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) + +#ifndef CONFIG_HIGHPTE +#define __pte_map(dir,km) pmd_page_vaddr(*(dir)) +#define __pte_unmap(pte,km) do { } while (0) +#else +#define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) +#define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) +#endif #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 6fdcbb709827f..5fa8dea5a3716 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -16,6 +16,7 @@ #include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/page-flags.h> +#include <linux/highmem.h> #include <asm/system.h> #include <asm/pgtable.h> -- GitLab From 35c9221acb133ecc9abd701a1fb6fa909d177a77 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 21 Aug 2009 07:07:46 +0100 Subject: [PATCH 0997/1002] ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform Add the cpu.c and dev.c and modify w90p910 platform to apply to use the common API(provided by cpu.c and dev.c) at the same time, I renamed all w90x900 to nuc900 in every c file of w90x900 platform and touchscreen's driver name. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/Makefile | 8 +- arch/arm/mach-w90x900/clksel.c | 12 +- arch/arm/mach-w90x900/clock.c | 4 +- arch/arm/mach-w90x900/clock.h | 8 +- arch/arm/mach-w90x900/{w90p910.c => cpu.c} | 122 +++--- arch/arm/mach-w90x900/cpu.h | 50 +-- arch/arm/mach-w90x900/dev.c | 389 +++++++++++++++++ arch/arm/mach-w90x900/gpio.c | 78 ++-- arch/arm/mach-w90x900/irq.c | 30 +- arch/arm/mach-w90x900/mach-nuc910evb.c | 44 ++ arch/arm/mach-w90x900/mach-w90p910evb.c | 407 ------------------ .../arm/mach-w90x900/{mfp-w90p910.c => mfp.c} | 38 +- arch/arm/mach-w90x900/nuc910.c | 60 +++ arch/arm/mach-w90x900/nuc910.h | 28 ++ arch/arm/mach-w90x900/time.c | 70 +-- drivers/input/touchscreen/w90p910_ts.c | 4 +- 16 files changed, 727 insertions(+), 625 deletions(-) rename arch/arm/mach-w90x900/{w90p910.c => cpu.c} (53%) create mode 100644 arch/arm/mach-w90x900/dev.c create mode 100644 arch/arm/mach-w90x900/mach-nuc910evb.c delete mode 100644 arch/arm/mach-w90x900/mach-w90p910evb.c rename arch/arm/mach-w90x900/{mfp-w90p910.c => mfp.c} (77%) create mode 100644 arch/arm/mach-w90x900/nuc910.c create mode 100644 arch/arm/mach-w90x900/nuc910.h diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile index 3ccd625455cf8..e38aa328e608c 100644 --- a/arch/arm/mach-w90x900/Makefile +++ b/arch/arm/mach-w90x900/Makefile @@ -4,12 +4,12 @@ # Object file lists. -obj-y := irq.o time.o mfp-w90p910.o gpio.o clock.o -obj-y += clksel.o +obj-y := irq.o time.o mfp.o gpio.o clock.o +obj-y += clksel.o dev.o cpu.o # W90X900 CPU support files -obj-$(CONFIG_CPU_W90P910) += w90p910.o +obj-$(CONFIG_CPU_W90P910) += nuc910.o # machine support -obj-$(CONFIG_MACH_W90P910EVB) += mach-w90p910evb.o +obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o diff --git a/arch/arm/mach-w90x900/clksel.c b/arch/arm/mach-w90x900/clksel.c index 5a77eb91cb16b..3de4a5211c3b1 100644 --- a/arch/arm/mach-w90x900/clksel.c +++ b/arch/arm/mach-w90x900/clksel.c @@ -42,13 +42,13 @@ static void clock_source_select(const char *dev_id, unsigned int clkval) clksel = __raw_readl(REG_CLKSEL); - if (strcmp(dev_id, "w90p910-ms") == 0) + if (strcmp(dev_id, "nuc900-ms") == 0) offset = MSOFFSET; - else if (strcmp(dev_id, "w90p910-atapi") == 0) + else if (strcmp(dev_id, "nuc900-atapi") == 0) offset = ATAOFFSET; - else if (strcmp(dev_id, "w90p910-lcd") == 0) + else if (strcmp(dev_id, "nuc900-lcd") == 0) offset = LCDOFFSET; - else if (strcmp(dev_id, "w90p910-audio") == 0) + else if (strcmp(dev_id, "nuc900-audio") == 0) offset = AUDOFFSET; else offset = CPUOFFSET; @@ -59,7 +59,7 @@ static void clock_source_select(const char *dev_id, unsigned int clkval) __raw_writel(clksel, REG_CLKSEL); } -void w90p910_clock_source(struct device *dev, unsigned char *src) +void nuc900_clock_source(struct device *dev, unsigned char *src) { unsigned int clkval; const char *dev_id; @@ -87,5 +87,5 @@ void w90p910_clock_source(struct device *dev, unsigned char *src) mutex_unlock(&clksel_sem); } -EXPORT_SYMBOL(w90p910_clock_source); +EXPORT_SYMBOL(nuc900_clock_source); diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c index 70b671096377f..b785994bab0a6 100644 --- a/arch/arm/mach-w90x900/clock.c +++ b/arch/arm/mach-w90x900/clock.c @@ -61,7 +61,7 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -void w90x900_clk_enable(struct clk *clk, int enable) +void nuc900_clk_enable(struct clk *clk, int enable) { unsigned int clocks = clk->cken; unsigned long clken; @@ -76,7 +76,7 @@ void w90x900_clk_enable(struct clk *clk, int enable) __raw_writel(clken, W90X900_VA_CLKPWR); } -void w90x900_subclk_enable(struct clk *clk, int enable) +void nuc900_subclk_enable(struct clk *clk, int enable) { unsigned int clocks = clk->cken; unsigned long clken; diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h index d2f0e50a70bfa..f5816a06eed6a 100644 --- a/arch/arm/mach-w90x900/clock.h +++ b/arch/arm/mach-w90x900/clock.h @@ -12,8 +12,8 @@ #include <asm/clkdev.h> -void w90x900_clk_enable(struct clk *clk, int enable); -void w90x900_subclk_enable(struct clk *clk, int enable); +void nuc900_clk_enable(struct clk *clk, int enable); +void nuc900_subclk_enable(struct clk *clk, int enable); void clks_register(struct clk_lookup *clks, size_t num); struct clk { @@ -24,13 +24,13 @@ struct clk { #define DEFINE_CLK(_name, _ctrlbit) \ struct clk clk_##_name = { \ - .enable = w90x900_clk_enable, \ + .enable = nuc900_clk_enable, \ .cken = (1 << _ctrlbit), \ } #define DEFINE_SUBCLK(_name, _ctrlbit) \ struct clk clk_##_name = { \ - .enable = w90x900_subclk_enable, \ + .enable = nuc900_subclk_enable, \ .cken = (1 << _ctrlbit), \ } diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/cpu.c similarity index 53% rename from arch/arm/mach-w90x900/w90p910.c rename to arch/arm/mach-w90x900/cpu.c index d33723b69d148..921cef991bf01 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/cpu.c @@ -1,13 +1,11 @@ /* - * linux/arch/arm/mach-w90x900/w90p910.c + * linux/arch/arm/mach-w90x900/cpu.c * - * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks - * - * Copyright (c) 2008 Nuvoton technology corporation. + * Copyright (c) 2009 Nuvoton corporation. * * Wan ZongShun <mcuos.com@gmail.com> * - * W90P910 cpu support + * NUC900 series cpu common support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,19 +39,12 @@ /* Initial IO mappings */ -static struct map_desc w90p910_iodesc[] __initdata = { +static struct map_desc nuc900_iodesc[] __initdata = { IODESC_ENT(IRQ), IODESC_ENT(GCR), IODESC_ENT(UART), IODESC_ENT(TIMER), IODESC_ENT(EBI), - IODESC_ENT(USBEHCIHOST), - IODESC_ENT(USBOHCIHOST), - IODESC_ENT(ADC), - IODESC_ENT(RTC), - IODESC_ENT(KPI), - IODESC_ENT(USBDEV), - /*IODESC_ENT(LCD),*/ }; /* Initial clock declarations. */ @@ -78,58 +69,45 @@ static DEFINE_CLK(adc, 28); static DEFINE_CLK(usi, 29); static DEFINE_CLK(ext, 0); -static struct clk_lookup w90p910_clkregs[] = { - DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), - DEF_CLKLOOK(&clk_audio, "w90p910-audio", NULL), - DEF_CLKLOOK(&clk_fmi, "w90p910-fmi", NULL), - DEF_CLKLOOK(&clk_ms, "w90p910-fmi", "MS"), - DEF_CLKLOOK(&clk_sd, "w90p910-fmi", "SD"), - DEF_CLKLOOK(&clk_dmac, "w90p910-dmac", NULL), - DEF_CLKLOOK(&clk_atapi, "w90p910-atapi", NULL), - DEF_CLKLOOK(&clk_emc, "w90p910-emc", NULL), - DEF_CLKLOOK(&clk_rmii, "w90p910-emc", "RMII"), - DEF_CLKLOOK(&clk_usbd, "w90p910-usbd", NULL), - DEF_CLKLOOK(&clk_usbh, "w90p910-usbh", NULL), - DEF_CLKLOOK(&clk_g2d, "w90p910-g2d", NULL), - DEF_CLKLOOK(&clk_pwm, "w90p910-pwm", NULL), - DEF_CLKLOOK(&clk_ps2, "w90p910-ps2", NULL), - DEF_CLKLOOK(&clk_kpi, "w90p910-kpi", NULL), - DEF_CLKLOOK(&clk_wdt, "w90p910-wdt", NULL), - DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), - DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), - DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), +static struct clk_lookup nuc900_clkregs[] = { + DEF_CLKLOOK(&clk_lcd, "nuc900-lcd", NULL), + DEF_CLKLOOK(&clk_audio, "nuc900-audio", NULL), + DEF_CLKLOOK(&clk_fmi, "nuc900-fmi", NULL), + DEF_CLKLOOK(&clk_ms, "nuc900-fmi", "MS"), + DEF_CLKLOOK(&clk_sd, "nuc900-fmi", "SD"), + DEF_CLKLOOK(&clk_dmac, "nuc900-dmac", NULL), + DEF_CLKLOOK(&clk_atapi, "nuc900-atapi", NULL), + DEF_CLKLOOK(&clk_emc, "nuc900-emc", NULL), + DEF_CLKLOOK(&clk_rmii, "nuc900-emc", "RMII"), + DEF_CLKLOOK(&clk_usbd, "nuc900-usbd", NULL), + DEF_CLKLOOK(&clk_usbh, "nuc900-usbh", NULL), + DEF_CLKLOOK(&clk_g2d, "nuc900-g2d", NULL), + DEF_CLKLOOK(&clk_pwm, "nuc900-pwm", NULL), + DEF_CLKLOOK(&clk_ps2, "nuc900-ps2", NULL), + DEF_CLKLOOK(&clk_kpi, "nuc900-kpi", NULL), + DEF_CLKLOOK(&clk_wdt, "nuc900-wdt", NULL), + DEF_CLKLOOK(&clk_gdma, "nuc900-gdma", NULL), + DEF_CLKLOOK(&clk_adc, "nuc900-adc", NULL), + DEF_CLKLOOK(&clk_usi, "nuc900-spi", NULL), DEF_CLKLOOK(&clk_ext, NULL, "ext"), }; /* Initial serial platform data */ -struct plat_serial8250_port w90p910_uart_data[] = { - W90X900_8250PORT(UART0), +struct plat_serial8250_port nuc900_uart_data[] = { + NUC900_8250PORT(UART0), }; -struct platform_device w90p910_serial_device = { +struct platform_device nuc900_serial_device = { .name = "serial8250", .id = PLAT8250_DEV_PLATFORM, .dev = { - .platform_data = w90p910_uart_data, + .platform_data = nuc900_uart_data, }, }; -/*Init W90P910 evb io*/ - -void __init w90p910_map_io(struct map_desc *mach_desc, int mach_size) -{ - unsigned long idcode = 0x0; - - iotable_init(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); - - idcode = __raw_readl(W90X900PDID); - if (idcode != W90P910_CPUID) - printk(KERN_ERR "CPU type 0x%08lx is not W90P910\n", idcode); -} - -/*Set W90P910 cpu frequence*/ -static int __init w90p910_set_clkval(unsigned int cpufreq) +/*Set NUC900 series cpu frequence*/ +static int __init nuc900_set_clkval(unsigned int cpufreq) { unsigned int pllclk, ahbclk, apbclk, val; @@ -178,7 +156,7 @@ static int __init w90p910_set_clkval(unsigned int cpufreq) return 0; } -static int __init w90p910_set_cpufreq(char *str) +static int __init nuc900_set_cpufreq(char *str) { unsigned long cpufreq, val; @@ -187,9 +165,9 @@ static int __init w90p910_set_cpufreq(char *str) strict_strtoul(str, 0, &cpufreq); - w90p910_clock_source(NULL, "ext"); + nuc900_clock_source(NULL, "ext"); - w90p910_set_clkval(cpufreq); + nuc900_set_clkval(cpufreq); mdelay(1); @@ -198,27 +176,37 @@ static int __init w90p910_set_cpufreq(char *str) val |= DEFAULTSKEW; __raw_writel(val, REG_CKSKEW); - w90p910_clock_source(NULL, "pll0"); + nuc900_clock_source(NULL, "pll0"); return 1; } -__setup("cpufreq=", w90p910_set_cpufreq); +__setup("cpufreq=", nuc900_set_cpufreq); -/*Init W90P910 clock*/ +/*Init NUC900 evb io*/ -void __init w90p910_init_clocks(void) +void __init nuc900_map_io(struct map_desc *mach_desc, int mach_size) { - clks_register(w90p910_clkregs, ARRAY_SIZE(w90p910_clkregs)); -} + unsigned long idcode = 0x0; -static int __init w90p910_init_cpu(void) -{ - return 0; + iotable_init(mach_desc, mach_size); + iotable_init(nuc900_iodesc, ARRAY_SIZE(nuc900_iodesc)); + + idcode = __raw_readl(NUC900PDID); + if (idcode == NUC910_CPUID) + printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode); + else if (idcode == NUC920_CPUID) + printk(KERN_INFO "CPU type 0x%08lx is NUC920\n", idcode); + else if (idcode == NUC950_CPUID) + printk(KERN_INFO "CPU type 0x%08lx is NUC950\n", idcode); + else if (idcode == NUC960_CPUID) + printk(KERN_INFO "CPU type 0x%08lx is NUC960\n", idcode); } -static int __init w90x900_arch_init(void) +/*Init NUC900 clock*/ + +void __init nuc900_init_clocks(void) { - return w90p910_init_cpu(); + clks_register(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs)); } -arch_initcall(w90x900_arch_init); + diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h index ddde959d89870..4d58ba164e252 100644 --- a/arch/arm/mach-w90x900/cpu.h +++ b/arch/arm/mach-w90x900/cpu.h @@ -6,7 +6,7 @@ * Copyright (c) 2008 Nuvoton technology corporation * All rights reserved. * - * Header file for W90X900 CPU support + * Header file for NUC900 CPU support * * Wan ZongShun <mcuos.com@gmail.com> * @@ -24,30 +24,7 @@ .type = MT_DEVICE, \ } -/*Cpu identifier register*/ - -#define W90X900PDID W90X900_VA_GCR -#define W90P910_CPUID 0x02900910 -#define W90P920_CPUID 0x02900920 -#define W90P950_CPUID 0x02900950 -#define W90N960_CPUID 0x02900960 - -struct w90x900_uartcfg; -struct map_desc; -struct sys_timer; - -/* core initialisation functions */ - -extern void w90x900_init_irq(void); -extern void w90p910_init_io(struct map_desc *mach_desc, int size); -extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no); -extern void w90p910_init_clocks(void); -extern void w90p910_map_io(struct map_desc *mach_desc, int size); -extern struct platform_device w90p910_serial_device; -extern struct sys_timer w90x900_timer; -extern void w90p910_clock_source(struct device *dev, unsigned char *src); - -#define W90X900_8250PORT(name) \ +#define NUC900_8250PORT(name) \ { \ .membase = name##_BA, \ .mapbase = name##_PA, \ @@ -57,3 +34,26 @@ extern void w90p910_clock_source(struct device *dev, unsigned char *src); .iotype = UPIO_MEM, \ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ } + +/*Cpu identifier register*/ + +#define NUC900PDID W90X900_VA_GCR +#define NUC910_CPUID 0x02900910 +#define NUC920_CPUID 0x02900920 +#define NUC950_CPUID 0x02900950 +#define NUC960_CPUID 0x02900960 + +/* extern file from cpu.c */ + +extern void nuc900_clock_source(struct device *dev, unsigned char *src); +extern void nuc900_init_clocks(void); +extern void nuc900_map_io(struct map_desc *mach_desc, int mach_size); +extern void nuc900_board_init(struct platform_device **device, int size); + +/* for either public between 910 and 920, or between 920 and 950 */ + +extern struct platform_device nuc900_serial_device; +extern struct platform_device nuc900_device_fmi; +extern struct platform_device nuc900_device_kpi; +extern struct platform_device nuc900_device_rtc; +extern struct platform_device nuc900_device_ts; diff --git a/arch/arm/mach-w90x900/dev.c b/arch/arm/mach-w90x900/dev.c new file mode 100644 index 0000000000000..2a6f98de48d25 --- /dev/null +++ b/arch/arm/mach-w90x900/dev.c @@ -0,0 +1,389 @@ +/* + * linux/arch/arm/mach-w90x900/dev.c + * + * Copyright (C) 2009 Nuvoton corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <linux/mtd/physmap.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach-types.h> + +#include <mach/regs-serial.h> +#include <mach/map.h> + +#include "cpu.h" + +/*NUC900 evb norflash driver data */ + +#define NUC900_FLASH_BASE 0xA0000000 +#define NUC900_FLASH_SIZE 0x400000 +#define SPIOFFSET 0x200 +#define SPIOREG_SIZE 0x100 + +static struct mtd_partition nuc900_flash_partitions[] = { + { + .name = "NOR Partition 1 for kernel (960K)", + .size = 0xF0000, + .offset = 0x10000, + }, + { + .name = "NOR Partition 2 for image (1M)", + .size = 0x100000, + .offset = 0x100000, + }, + { + .name = "NOR Partition 3 for user (2M)", + .size = 0x200000, + .offset = 0x00200000, + } +}; + +static struct physmap_flash_data nuc900_flash_data = { + .width = 2, + .parts = nuc900_flash_partitions, + .nr_parts = ARRAY_SIZE(nuc900_flash_partitions), +}; + +static struct resource nuc900_flash_resources[] = { + { + .start = NUC900_FLASH_BASE, + .end = NUC900_FLASH_BASE + NUC900_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device nuc900_flash_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &nuc900_flash_data, + }, + .resource = nuc900_flash_resources, + .num_resources = ARRAY_SIZE(nuc900_flash_resources), +}; + +/* USB EHCI Host Controller */ + +static struct resource nuc900_usb_ehci_resource[] = { + [0] = { + .start = W90X900_PA_USBEHCIHOST, + .end = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USBH, + .end = IRQ_USBH, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 nuc900_device_usb_ehci_dmamask = 0xffffffffUL; + +static struct platform_device nuc900_device_usb_ehci = { + .name = "nuc900-ehci", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_usb_ehci_resource), + .resource = nuc900_usb_ehci_resource, + .dev = { + .dma_mask = &nuc900_device_usb_ehci_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +/* USB OHCI Host Controller */ + +static struct resource nuc900_usb_ohci_resource[] = { + [0] = { + .start = W90X900_PA_USBOHCIHOST, + .end = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USBH, + .end = IRQ_USBH, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 nuc900_device_usb_ohci_dmamask = 0xffffffffUL; +static struct platform_device nuc900_device_usb_ohci = { + .name = "nuc900-ohci", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_usb_ohci_resource), + .resource = nuc900_usb_ohci_resource, + .dev = { + .dma_mask = &nuc900_device_usb_ohci_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +/* USB Device (Gadget)*/ + +static struct resource nuc900_usbgadget_resource[] = { + [0] = { + .start = W90X900_PA_USBDEV, + .end = W90X900_PA_USBDEV + W90X900_SZ_USBDEV - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USBD, + .end = IRQ_USBD, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device nuc900_device_usbgadget = { + .name = "nuc900-usbgadget", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_usbgadget_resource), + .resource = nuc900_usbgadget_resource, +}; + +/* MAC device */ + +static struct resource nuc900_emc_resource[] = { + [0] = { + .start = W90X900_PA_EMC, + .end = W90X900_PA_EMC + W90X900_SZ_EMC - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_EMCTX, + .end = IRQ_EMCTX, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_EMCRX, + .end = IRQ_EMCRX, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 nuc900_device_emc_dmamask = 0xffffffffUL; +static struct platform_device nuc900_device_emc = { + .name = "nuc900-emc", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_emc_resource), + .resource = nuc900_emc_resource, + .dev = { + .dma_mask = &nuc900_device_emc_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +/* SPI device */ + +static struct resource nuc900_spi_resource[] = { + [0] = { + .start = W90X900_PA_I2C + SPIOFFSET, + .end = W90X900_PA_I2C + SPIOFFSET + SPIOREG_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SSP, + .end = IRQ_SSP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device nuc900_device_spi = { + .name = "nuc900-spi", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_spi_resource), + .resource = nuc900_spi_resource, +}; + +/* spi device, spi flash info */ + +static struct mtd_partition nuc900_spi_flash_partitions[] = { + { + .name = "bootloader(spi)", + .size = 0x0100000, + .offset = 0, + }, +}; + +static struct flash_platform_data nuc900_spi_flash_data = { + .name = "m25p80", + .parts = nuc900_spi_flash_partitions, + .nr_parts = ARRAY_SIZE(nuc900_spi_flash_partitions), + .type = "w25x16", +}; + +static struct spi_board_info nuc900_spi_board_info[] __initdata = { + { + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &nuc900_spi_flash_data, + .mode = SPI_MODE_0, + }, +}; + +/* WDT Device */ + +static struct resource nuc900_wdt_resource[] = { + [0] = { + .start = W90X900_PA_TIMER, + .end = W90X900_PA_TIMER + W90X900_SZ_TIMER - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_WDT, + .end = IRQ_WDT, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device nuc900_device_wdt = { + .name = "nuc900-wdt", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_wdt_resource), + .resource = nuc900_wdt_resource, +}; + +/* + * public device definition between 910 and 920, or 910 + * and 950 or 950 and 960...,their dev platform register + * should be in specific file such as nuc950, nuc960 c + * files rather than the public dev.c file here. so the + * corresponding platform_device definition should not be + * static. +*/ + +/* RTC controller*/ + +static struct resource nuc900_rtc_resource[] = { + [0] = { + .start = W90X900_PA_RTC, + .end = W90X900_PA_RTC + 0xff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC, + .end = IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device nuc900_device_rtc = { + .name = "nuc900-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_rtc_resource), + .resource = nuc900_rtc_resource, +}; + +/*TouchScreen controller*/ + +static struct resource nuc900_ts_resource[] = { + [0] = { + .start = W90X900_PA_ADC, + .end = W90X900_PA_ADC + W90X900_SZ_ADC-1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_ADC, + .end = IRQ_ADC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device nuc900_device_ts = { + .name = "nuc900-ts", + .id = -1, + .resource = nuc900_ts_resource, + .num_resources = ARRAY_SIZE(nuc900_ts_resource), +}; + +/* FMI Device */ + +static struct resource nuc900_fmi_resource[] = { + [0] = { + .start = W90X900_PA_FMI, + .end = W90X900_PA_FMI + W90X900_SZ_FMI - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_FMI, + .end = IRQ_FMI, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device nuc900_device_fmi = { + .name = "nuc900-fmi", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_fmi_resource), + .resource = nuc900_fmi_resource, +}; + +/* KPI controller*/ + +static struct resource nuc900_kpi_resource[] = { + [0] = { + .start = W90X900_PA_KPI, + .end = W90X900_PA_KPI + W90X900_SZ_KPI - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_KPI, + .end = IRQ_KPI, + .flags = IORESOURCE_IRQ, + } + +}; + +struct platform_device nuc900_device_kpi = { + .name = "nuc900-kpi", + .id = -1, + .num_resources = ARRAY_SIZE(nuc900_kpi_resource), + .resource = nuc900_kpi_resource, +}; + +/*Here should be your evb resourse,such as LCD*/ + +static struct platform_device *nuc900_public_dev[] __initdata = { + &nuc900_serial_device, + &nuc900_flash_device, + &nuc900_device_usb_ehci, + &nuc900_device_usb_ohci, + &nuc900_device_usbgadget, + &nuc900_device_emc, + &nuc900_device_spi, + &nuc900_device_wdt, +}; + +/* Provide adding specific CPU platform devices API */ + +void __init nuc900_board_init(struct platform_device **device, int size) +{ + platform_add_devices(device, size); + platform_add_devices(nuc900_public_dev, ARRAY_SIZE(nuc900_public_dev)); + spi_register_board_info(nuc900_spi_board_info, + ARRAY_SIZE(nuc900_spi_board_info)); +} + diff --git a/arch/arm/mach-w90x900/gpio.c b/arch/arm/mach-w90x900/gpio.c index c72e0dfa18256..ba05aec7ea4b9 100644 --- a/arch/arm/mach-w90x900/gpio.c +++ b/arch/arm/mach-w90x900/gpio.c @@ -1,7 +1,7 @@ /* - * linux/arch/arm/mach-w90p910/gpio.c + * linux/arch/arm/mach-w90x900/gpio.c * - * Generic w90p910 GPIO handling + * Generic nuc900 GPIO handling * * Wan ZongShun <mcuos.com@gmail.com> * @@ -30,31 +30,31 @@ #define GPIO_IN (0x0C) #define GROUPINERV (0x10) #define GPIO_GPIO(Nb) (0x00000001 << (Nb)) -#define to_w90p910_gpio_chip(c) container_of(c, struct w90p910_gpio_chip, chip) +#define to_nuc900_gpio_chip(c) container_of(c, struct nuc900_gpio_chip, chip) -#define W90P910_GPIO_CHIP(name, base_gpio, nr_gpio) \ +#define NUC900_GPIO_CHIP(name, base_gpio, nr_gpio) \ { \ .chip = { \ .label = name, \ - .direction_input = w90p910_dir_input, \ - .direction_output = w90p910_dir_output, \ - .get = w90p910_gpio_get, \ - .set = w90p910_gpio_set, \ + .direction_input = nuc900_dir_input, \ + .direction_output = nuc900_dir_output, \ + .get = nuc900_gpio_get, \ + .set = nuc900_gpio_set, \ .base = base_gpio, \ .ngpio = nr_gpio, \ } \ } -struct w90p910_gpio_chip { +struct nuc900_gpio_chip { struct gpio_chip chip; void __iomem *regbase; /* Base of group register*/ spinlock_t gpio_lock; }; -static int w90p910_gpio_get(struct gpio_chip *chip, unsigned offset) +static int nuc900_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip); - void __iomem *pio = w90p910_gpio->regbase + GPIO_IN; + struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip); + void __iomem *pio = nuc900_gpio->regbase + GPIO_IN; unsigned int regval; regval = __raw_readl(pio); @@ -63,14 +63,14 @@ static int w90p910_gpio_get(struct gpio_chip *chip, unsigned offset) return (regval != 0); } -static void w90p910_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static void nuc900_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { - struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip); - void __iomem *pio = w90p910_gpio->regbase + GPIO_OUT; + struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip); + void __iomem *pio = nuc900_gpio->regbase + GPIO_OUT; unsigned int regval; unsigned long flags; - spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags); + spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags); regval = __raw_readl(pio); @@ -81,36 +81,36 @@ static void w90p910_gpio_set(struct gpio_chip *chip, unsigned offset, int val) __raw_writel(regval, pio); - spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags); + spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags); } -static int w90p910_dir_input(struct gpio_chip *chip, unsigned offset) +static int nuc900_dir_input(struct gpio_chip *chip, unsigned offset) { - struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip); - void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR; + struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip); + void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR; unsigned int regval; unsigned long flags; - spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags); + spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags); regval = __raw_readl(pio); regval &= ~GPIO_GPIO(offset); __raw_writel(regval, pio); - spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags); + spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags); return 0; } -static int w90p910_dir_output(struct gpio_chip *chip, unsigned offset, int val) +static int nuc900_dir_output(struct gpio_chip *chip, unsigned offset, int val) { - struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip); - void __iomem *outreg = w90p910_gpio->regbase + GPIO_OUT; - void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR; + struct nuc900_gpio_chip *nuc900_gpio = to_nuc900_gpio_chip(chip); + void __iomem *outreg = nuc900_gpio->regbase + GPIO_OUT; + void __iomem *pio = nuc900_gpio->regbase + GPIO_DIR; unsigned int regval; unsigned long flags; - spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags); + spin_lock_irqsave(&nuc900_gpio->gpio_lock, flags); regval = __raw_readl(pio); regval |= GPIO_GPIO(offset); @@ -125,28 +125,28 @@ static int w90p910_dir_output(struct gpio_chip *chip, unsigned offset, int val) __raw_writel(regval, outreg); - spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags); + spin_unlock_irqrestore(&nuc900_gpio->gpio_lock, flags); return 0; } -static struct w90p910_gpio_chip w90p910_gpio[] = { - W90P910_GPIO_CHIP("GROUPC", 0, 16), - W90P910_GPIO_CHIP("GROUPD", 16, 10), - W90P910_GPIO_CHIP("GROUPE", 26, 14), - W90P910_GPIO_CHIP("GROUPF", 40, 10), - W90P910_GPIO_CHIP("GROUPG", 50, 17), - W90P910_GPIO_CHIP("GROUPH", 67, 8), - W90P910_GPIO_CHIP("GROUPI", 75, 17), +static struct nuc900_gpio_chip nuc900_gpio[] = { + NUC900_GPIO_CHIP("GROUPC", 0, 16), + NUC900_GPIO_CHIP("GROUPD", 16, 10), + NUC900_GPIO_CHIP("GROUPE", 26, 14), + NUC900_GPIO_CHIP("GROUPF", 40, 10), + NUC900_GPIO_CHIP("GROUPG", 50, 17), + NUC900_GPIO_CHIP("GROUPH", 67, 8), + NUC900_GPIO_CHIP("GROUPI", 75, 17), }; -void __init w90p910_init_gpio(int nr_group) +void __init nuc900_init_gpio(int nr_group) { unsigned i; - struct w90p910_gpio_chip *gpio_chip; + struct nuc900_gpio_chip *gpio_chip; for (i = 0; i < nr_group; i++) { - gpio_chip = &w90p910_gpio[i]; + gpio_chip = &nuc900_gpio[i]; spin_lock_init(&gpio_chip->gpio_lock); gpio_chip->regbase = GPIO_BASE + i * GROUPINERV; gpiochip_add(&gpio_chip->chip); diff --git a/arch/arm/mach-w90x900/irq.c b/arch/arm/mach-w90x900/irq.c index a296c9b81d244..0ce9d8e867eb1 100644 --- a/arch/arm/mach-w90x900/irq.c +++ b/arch/arm/mach-w90x900/irq.c @@ -36,13 +36,13 @@ struct group_irq { static DEFINE_SPINLOCK(groupirq_lock); -#define DEFINE_GROUP(_name, _ctrlbit, _num) \ -struct group_irq group_##_name = { \ - .enable = w90x900_group_enable, \ - .gpen = ((2 ^ _num) - 1) << _ctrlbit, \ +#define DEFINE_GROUP(_name, _ctrlbit, _num) \ +struct group_irq group_##_name = { \ + .enable = nuc900_group_enable, \ + .gpen = ((1 << _num) - 1) << _ctrlbit, \ } -static void w90x900_group_enable(struct group_irq *gpirq, int enable); +static void nuc900_group_enable(struct group_irq *gpirq, int enable); static DEFINE_GROUP(nirq0, 0, 4); static DEFINE_GROUP(nirq1, 4, 4); @@ -77,7 +77,7 @@ static void group_irq_disable(struct group_irq *group_irq) spin_unlock_irqrestore(&groupirq_lock, flags); } -static void w90x900_group_enable(struct group_irq *gpirq, int enable) +static void nuc900_group_enable(struct group_irq *gpirq, int enable) { unsigned int groupen = gpirq->gpen; unsigned long regval; @@ -92,7 +92,7 @@ static void w90x900_group_enable(struct group_irq *gpirq, int enable) __raw_writel(regval, REG_AIC_GEN); } -static void w90x900_irq_mask(unsigned int irq) +static void nuc900_irq_mask(unsigned int irq) { struct group_irq *group_irq; @@ -143,12 +143,12 @@ static void w90x900_irq_mask(unsigned int irq) * to REG_AIC_EOSCR for ACK */ -static void w90x900_irq_ack(unsigned int irq) +static void nuc900_irq_ack(unsigned int irq) { __raw_writel(0x01, REG_AIC_EOSCR); } -static void w90x900_irq_unmask(unsigned int irq) +static void nuc900_irq_unmask(unsigned int irq) { struct group_irq *group_irq; @@ -194,20 +194,20 @@ static void w90x900_irq_unmask(unsigned int irq) group_irq_enable(group_irq); } -static struct irq_chip w90x900_irq_chip = { - .ack = w90x900_irq_ack, - .mask = w90x900_irq_mask, - .unmask = w90x900_irq_unmask, +static struct irq_chip nuc900_irq_chip = { + .ack = nuc900_irq_ack, + .mask = nuc900_irq_mask, + .unmask = nuc900_irq_unmask, }; -void __init w90x900_init_irq(void) +void __init nuc900_init_irq(void) { int irqno; __raw_writel(0xFFFFFFFE, REG_AIC_MDCR); for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) { - set_irq_chip(irqno, &w90x900_irq_chip); + set_irq_chip(irqno, &nuc900_irq_chip); set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c new file mode 100644 index 0000000000000..ec05bda946f31 --- /dev/null +++ b/arch/arm/mach-w90x900/mach-nuc910evb.c @@ -0,0 +1,44 @@ +/* + * linux/arch/arm/mach-w90x900/mach-nuc910evb.c + * + * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche + * + * Copyright (C) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach-types.h> +#include <mach/map.h> + +#include "nuc910.h" + +static void __init nuc910evb_map_io(void) +{ + nuc910_map_io(); + nuc910_init_clocks(); +} + +static void __init nuc910evb_init(void) +{ + nuc910_board_init(); +} + +MACHINE_START(W90P910EVB, "W90P910EVB") + /* Maintainer: Wan ZongShun */ + .phys_io = W90X900_PA_UART, + .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, + .boot_params = 0, + .map_io = nuc910evb_map_io, + .init_irq = nuc900_init_irq, + .init_machine = nuc910evb_init, + .timer = &nuc900_timer, +MACHINE_END diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c deleted file mode 100644 index 117578aed6812..0000000000000 --- a/arch/arm/mach-w90x900/mach-w90p910evb.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * linux/arch/arm/mach-w90x900/mach-w90p910evb.c - * - * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche - * - * Copyright (C) 2008 Nuvoton technology corporation. - * - * Wan ZongShun <mcuos.com@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation;version 2 of the License. - * - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/init.h> -#include <linux/platform_device.h> - -#include <linux/mtd/physmap.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> - -#include <linux/spi/spi.h> -#include <linux/spi/flash.h> - -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> -#include <asm/mach-types.h> - -#include <mach/regs-serial.h> -#include <mach/map.h> - -#include "cpu.h" -/*w90p910 evb norflash driver data */ - -#define W90P910_FLASH_BASE 0xA0000000 -#define W90P910_FLASH_SIZE 0x400000 -#define SPIOFFSET 0x200 -#define SPIOREG_SIZE 0x100 - -static struct mtd_partition w90p910_flash_partitions[] = { - { - .name = "NOR Partition 1 for kernel (960K)", - .size = 0xF0000, - .offset = 0x10000, - }, - { - .name = "NOR Partition 2 for image (1M)", - .size = 0x100000, - .offset = 0x100000, - }, - { - .name = "NOR Partition 3 for user (2M)", - .size = 0x200000, - .offset = 0x00200000, - } -}; - -static struct physmap_flash_data w90p910_flash_data = { - .width = 2, - .parts = w90p910_flash_partitions, - .nr_parts = ARRAY_SIZE(w90p910_flash_partitions), -}; - -static struct resource w90p910_flash_resources[] = { - { - .start = W90P910_FLASH_BASE, - .end = W90P910_FLASH_BASE + W90P910_FLASH_SIZE - 1, - .flags = IORESOURCE_MEM, - } -}; - -static struct platform_device w90p910_flash_device = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &w90p910_flash_data, - }, - .resource = w90p910_flash_resources, - .num_resources = ARRAY_SIZE(w90p910_flash_resources), -}; - -/* USB EHCI Host Controller */ - -static struct resource w90x900_usb_ehci_resource[] = { - [0] = { - .start = W90X900_PA_USBEHCIHOST, - .end = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_USBH, - .end = IRQ_USBH, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 w90x900_device_usb_ehci_dmamask = 0xffffffffUL; - -struct platform_device w90x900_device_usb_ehci = { - .name = "w90x900-ehci", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_usb_ehci_resource), - .resource = w90x900_usb_ehci_resource, - .dev = { - .dma_mask = &w90x900_device_usb_ehci_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; -EXPORT_SYMBOL(w90x900_device_usb_ehci); - -/* USB OHCI Host Controller */ - -static struct resource w90x900_usb_ohci_resource[] = { - [0] = { - .start = W90X900_PA_USBOHCIHOST, - .end = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_USBH, - .end = IRQ_USBH, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 w90x900_device_usb_ohci_dmamask = 0xffffffffUL; -struct platform_device w90x900_device_usb_ohci = { - .name = "w90x900-ohci", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_usb_ohci_resource), - .resource = w90x900_usb_ohci_resource, - .dev = { - .dma_mask = &w90x900_device_usb_ohci_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; -EXPORT_SYMBOL(w90x900_device_usb_ohci); - -/*TouchScreen controller*/ - -static struct resource w90x900_ts_resource[] = { - [0] = { - .start = W90X900_PA_ADC, - .end = W90X900_PA_ADC + W90X900_SZ_ADC-1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_ADC, - .end = IRQ_ADC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device w90x900_device_ts = { - .name = "w90x900-ts", - .id = -1, - .resource = w90x900_ts_resource, - .num_resources = ARRAY_SIZE(w90x900_ts_resource), -}; -EXPORT_SYMBOL(w90x900_device_ts); - -/* RTC controller*/ - -static struct resource w90x900_rtc_resource[] = { - [0] = { - .start = W90X900_PA_RTC, - .end = W90X900_PA_RTC + 0xff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_RTC, - .end = IRQ_RTC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device w90x900_device_rtc = { - .name = "w90x900-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_rtc_resource), - .resource = w90x900_rtc_resource, -}; -EXPORT_SYMBOL(w90x900_device_rtc); - -/* KPI controller*/ - -static struct resource w90x900_kpi_resource[] = { - [0] = { - .start = W90X900_PA_KPI, - .end = W90X900_PA_KPI + W90X900_SZ_KPI - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_KPI, - .end = IRQ_KPI, - .flags = IORESOURCE_IRQ, - } - -}; - -struct platform_device w90x900_device_kpi = { - .name = "w90x900-kpi", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_kpi_resource), - .resource = w90x900_kpi_resource, -}; -EXPORT_SYMBOL(w90x900_device_kpi); - -/* USB Device (Gadget)*/ - -static struct resource w90x900_usbgadget_resource[] = { - [0] = { - .start = W90X900_PA_USBDEV, - .end = W90X900_PA_USBDEV + W90X900_SZ_USBDEV - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_USBD, - .end = IRQ_USBD, - .flags = IORESOURCE_IRQ, - } -}; - -struct platform_device w90x900_device_usbgadget = { - .name = "w90x900-usbgadget", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_usbgadget_resource), - .resource = w90x900_usbgadget_resource, -}; -EXPORT_SYMBOL(w90x900_device_usbgadget); - -/* FMI Device */ - -static struct resource w90p910_fmi_resource[] = { - [0] = { - .start = W90X900_PA_FMI, - .end = W90X900_PA_FMI + W90X900_SZ_FMI - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_FMI, - .end = IRQ_FMI, - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device w90p910_device_fmi = { - .name = "w90p910-fmi", - .id = -1, - .num_resources = ARRAY_SIZE(w90p910_fmi_resource), - .resource = w90p910_fmi_resource, -}; - -/* MAC device */ - -static struct resource w90x900_emc_resource[] = { - [0] = { - .start = W90X900_PA_EMC, - .end = W90X900_PA_EMC + W90X900_SZ_EMC - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_EMCTX, - .end = IRQ_EMCTX, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_EMCRX, - .end = IRQ_EMCRX, - .flags = IORESOURCE_IRQ, - } -}; - -static u64 w90x900_device_emc_dmamask = 0xffffffffUL; -static struct platform_device w90p910_device_emc = { - .name = "w90p910-emc", - .id = -1, - .num_resources = ARRAY_SIZE(w90x900_emc_resource), - .resource = w90x900_emc_resource, - .dev = { - .dma_mask = &w90x900_device_emc_dmamask, - .coherent_dma_mask = 0xffffffffUL - } -}; - -/* SPI device */ - -static struct resource w90p910_spi_resource[] = { - [0] = { - .start = W90X900_PA_I2C + SPIOFFSET, - .end = W90X900_PA_I2C + SPIOFFSET + SPIOREG_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_SSP, - .end = IRQ_SSP, - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device w90p910_device_spi = { - .name = "w90p910-spi", - .id = -1, - .num_resources = ARRAY_SIZE(w90p910_spi_resource), - .resource = w90p910_spi_resource, -}; - -/* spi device, spi flash info */ - -static struct mtd_partition w90p910_spi_flash_partitions[] = { - { - .name = "bootloader(spi)", - .size = 0x0100000, - .offset = 0, - }, -}; - -static struct flash_platform_data w90p910_spi_flash_data = { - .name = "m25p80", - .parts = w90p910_spi_flash_partitions, - .nr_parts = ARRAY_SIZE(w90p910_spi_flash_partitions), - .type = "w25x16", -}; - -static struct spi_board_info w90p910_spi_board_info[] __initdata = { - { - .modalias = "m25p80", - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 1, - .platform_data = &w90p910_spi_flash_data, - .mode = SPI_MODE_0, - }, -}; - -/* WDT Device */ - -static struct resource w90p910_wdt_resource[] = { - [0] = { - .start = W90X900_PA_TIMER, - .end = W90X900_PA_TIMER + W90X900_SZ_TIMER - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_WDT, - .end = IRQ_WDT, - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device w90p910_device_wdt = { - .name = "w90p910-wdt", - .id = -1, - .num_resources = ARRAY_SIZE(w90p910_wdt_resource), - .resource = w90p910_wdt_resource, -}; - -static struct map_desc w90p910_iodesc[] __initdata = { -}; - -/*Here should be your evb resourse,such as LCD*/ - -static struct platform_device *w90p910evb_dev[] __initdata = { - &w90p910_serial_device, - &w90p910_flash_device, - &w90x900_device_usb_ehci, - &w90x900_device_usb_ohci, - &w90x900_device_ts, - &w90x900_device_rtc, - &w90x900_device_kpi, - &w90x900_device_usbgadget, - &w90p910_device_fmi, - &w90p910_device_emc, - &w90p910_device_spi, - &w90p910_device_wdt, -}; - -static void __init w90p910evb_map_io(void) -{ - w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); - w90p910_init_clocks(); -} - -static void __init w90p910evb_init(void) -{ - platform_add_devices(w90p910evb_dev, ARRAY_SIZE(w90p910evb_dev)); - spi_register_board_info(w90p910_spi_board_info, - ARRAY_SIZE(w90p910_spi_board_info)); -} - -MACHINE_START(W90P910EVB, "W90P910EVB") - /* Maintainer: Wan ZongShun */ - .phys_io = W90X900_PA_UART, - .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, - .boot_params = 0, - .map_io = w90p910evb_map_io, - .init_irq = w90x900_init_irq, - .init_machine = w90p910evb_init, - .timer = &w90x900_timer, -MACHINE_END diff --git a/arch/arm/mach-w90x900/mfp-w90p910.c b/arch/arm/mach-w90x900/mfp.c similarity index 77% rename from arch/arm/mach-w90x900/mfp-w90p910.c rename to arch/arm/mach-w90x900/mfp.c index 4533098a0ee48..a47dc9a708ee0 100644 --- a/arch/arm/mach-w90x900/mfp-w90p910.c +++ b/arch/arm/mach-w90x900/mfp.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-w90x900/mfp-w90p910.c + * linux/arch/arm/mach-w90x900/mfp.c * * Copyright (c) 2008 Nuvoton technology corporation * @@ -55,7 +55,7 @@ void mfp_set_groupf(struct device *dev) mfpen = __raw_readl(REG_MFSEL); - if (strcmp(dev_id, "w90p910-emc") == 0) + if (strcmp(dev_id, "nuc900-emc") == 0) mfpen |= GPSELF;/*enable mac*/ else mfpen &= ~GPSELF;/*GPIOF[9:0]*/ @@ -79,16 +79,16 @@ void mfp_set_groupc(struct device *dev) mfpen = __raw_readl(REG_MFSEL); - if (strcmp(dev_id, "w90p910-lcd") == 0) + if (strcmp(dev_id, "nuc900-lcd") == 0) mfpen |= GPSELC;/*enable lcd*/ - else if (strcmp(dev_id, "w90p910-kpi") == 0) { - mfpen &= (~GPSELC);/*enable kpi*/ - mfpen |= ENKPI; - } else if (strcmp(dev_id, "w90p910-nand") == 0) { - mfpen &= (~GPSELC);/*enable nand*/ - mfpen |= ENNAND; - } else - mfpen &= (~GPSELC);/*GPIOC[14:0]*/ + else if (strcmp(dev_id, "nuc900-kpi") == 0) { + mfpen &= (~GPSELC);/*enable kpi*/ + mfpen |= ENKPI; + } else if (strcmp(dev_id, "nuc900-nand") == 0) { + mfpen &= (~GPSELC);/*enable nand*/ + mfpen |= ENNAND; + } else + mfpen &= (~GPSELC);/*GPIOC[14:0]*/ __raw_writel(mfpen, REG_MFSEL); @@ -111,12 +111,12 @@ void mfp_set_groupi(struct device *dev) mfpen &= ~GPSELEI1;/*default gpio16*/ - if (strcmp(dev_id, "w90p910-wdog") == 0) + if (strcmp(dev_id, "nuc900-wdog") == 0) mfpen |= GPSELEI1;/*enable wdog*/ - else if (strcmp(dev_id, "w90p910-atapi") == 0) - mfpen |= GPSELEI0;/*enable atapi*/ - else if (strcmp(dev_id, "w90p910-keypad") == 0) - mfpen &= ~GPSELEI0;/*enable keypad*/ + else if (strcmp(dev_id, "nuc900-atapi") == 0) + mfpen |= GPSELEI0;/*enable atapi*/ + else if (strcmp(dev_id, "nuc900-keypad") == 0) + mfpen &= ~GPSELEI0;/*enable keypad*/ __raw_writel(mfpen, REG_MFSEL); @@ -137,13 +137,13 @@ void mfp_set_groupg(struct device *dev) mfpen = __raw_readl(REG_MFSEL); - if (strcmp(dev_id, "w90p910-spi") == 0) { + if (strcmp(dev_id, "nuc900-spi") == 0) { mfpen &= ~(GPIOG0TO1 | GPIOG2TO3); mfpen |= ENSPI;/*enable spi*/ - } else if (strcmp(dev_id, "w90p910-i2c0") == 0) { + } else if (strcmp(dev_id, "nuc900-i2c0") == 0) { mfpen &= ~(GPIOG0TO1); mfpen |= ENI2C0;/*enable i2c0*/ - } else if (strcmp(dev_id, "w90p910-i2c1") == 0) { + } else if (strcmp(dev_id, "nuc900-i2c1") == 0) { mfpen &= ~(GPIOG2TO3); mfpen |= ENI2C1;/*enable i2c1*/ } else { diff --git a/arch/arm/mach-w90x900/nuc910.c b/arch/arm/mach-w90x900/nuc910.c new file mode 100644 index 0000000000000..656f03b3b629f --- /dev/null +++ b/arch/arm/mach-w90x900/nuc910.c @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/mach-w90x900/nuc910.c + * + * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks + * + * Copyright (c) 2009 Nuvoton corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * NUC910 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/map.h> +#include <mach/hardware.h> +#include "cpu.h" +#include "clock.h" + +/* define specific CPU platform device */ + +static struct platform_device *nuc910_dev[] __initdata = { + &nuc900_device_ts, + &nuc900_device_rtc, +}; + +/* define specific CPU platform io map */ + +static struct map_desc nuc910evb_iodesc[] __initdata = { + IODESC_ENT(USBEHCIHOST), + IODESC_ENT(USBOHCIHOST), + IODESC_ENT(KPI), + IODESC_ENT(USBDEV), + IODESC_ENT(ADC), +}; + +/*Init NUC910 evb io*/ + +void __init nuc910_map_io(void) +{ + nuc900_map_io(nuc910evb_iodesc, ARRAY_SIZE(nuc910evb_iodesc)); +} + +/*Init NUC910 clock*/ + +void __init nuc910_init_clocks(void) +{ + nuc900_init_clocks(); +} + +/*Init NUC910 board info*/ + +void __init nuc910_board_init(void) +{ + nuc900_board_init(nuc910_dev, ARRAY_SIZE(nuc910_dev)); +} diff --git a/arch/arm/mach-w90x900/nuc910.h b/arch/arm/mach-w90x900/nuc910.h new file mode 100644 index 0000000000000..83e9ba5fc26c9 --- /dev/null +++ b/arch/arm/mach-w90x900/nuc910.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-w90x900/nuc910.h + * + * Copyright (c) 2008 Nuvoton corporation + * + * Header file for NUC900 CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +struct map_desc; +struct sys_timer; + +/* core initialisation functions */ + +extern void nuc900_init_irq(void); +extern struct sys_timer nuc900_timer; + +/* extern file from nuc910.c */ + +extern void nuc910_board_init(void); +extern void nuc910_init_clocks(void); +extern void nuc910_map_io(void); diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 5e06770e60143..4128af870b41a 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -44,7 +44,7 @@ unsigned int timer0_load; -static void w90p910_clockevent_setmode(enum clock_event_mode mode, +static void nuc900_clockevent_setmode(enum clock_event_mode mode, struct clock_event_device *clk) { unsigned int val; @@ -71,7 +71,7 @@ static void w90p910_clockevent_setmode(enum clock_event_mode mode, __raw_writel(val, REG_TCSR0); } -static int w90p910_clockevent_setnextevent(unsigned long evt, +static int nuc900_clockevent_setnextevent(unsigned long evt, struct clock_event_device *clk) { unsigned int val; @@ -85,20 +85,20 @@ static int w90p910_clockevent_setnextevent(unsigned long evt, return 0; } -static struct clock_event_device w90p910_clockevent_device = { - .name = "w90p910-timer0", +static struct clock_event_device nuc900_clockevent_device = { + .name = "nuc900-timer0", .shift = 32, .features = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = w90p910_clockevent_setmode, - .set_next_event = w90p910_clockevent_setnextevent, + .set_mode = nuc900_clockevent_setmode, + .set_next_event = nuc900_clockevent_setnextevent, .rating = 300, }; /*IRQ handler for the timer*/ -static irqreturn_t w90p910_timer0_interrupt(int irq, void *dev_id) +static irqreturn_t nuc900_timer0_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &w90p910_clockevent_device; + struct clock_event_device *evt = &nuc900_clockevent_device; __raw_writel(0x01, REG_TISR); /* clear TIF0 */ @@ -106,40 +106,40 @@ static irqreturn_t w90p910_timer0_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct irqaction w90p910_timer0_irq = { - .name = "w90p910-timer0", +static struct irqaction nuc900_timer0_irq = { + .name = "nuc900-timer0", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = w90p910_timer0_interrupt, + .handler = nuc900_timer0_interrupt, }; -static void __init w90p910_clockevents_init(unsigned int rate) +static void __init nuc900_clockevents_init(unsigned int rate) { - w90p910_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, - w90p910_clockevent_device.shift); - w90p910_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, - &w90p910_clockevent_device); - w90p910_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, - &w90p910_clockevent_device); - w90p910_clockevent_device.cpumask = cpumask_of(0); - - clockevents_register_device(&w90p910_clockevent_device); + nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, + nuc900_clockevent_device.shift); + nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, + &nuc900_clockevent_device); + nuc900_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, + &nuc900_clockevent_device); + nuc900_clockevent_device.cpumask = cpumask_of(0); + + clockevents_register_device(&nuc900_clockevent_device); } -static cycle_t w90p910_get_cycles(struct clocksource *cs) +static cycle_t nuc900_get_cycles(struct clocksource *cs) { return ~__raw_readl(REG_TDR1); } -static struct clocksource clocksource_w90p910 = { - .name = "w90p910-timer1", +static struct clocksource clocksource_nuc900 = { + .name = "nuc900-timer1", .rating = 200, - .read = w90p910_get_cycles, + .read = nuc900_get_cycles, .mask = CLOCKSOURCE_MASK(32), .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static void __init w90p910_clocksource_init(unsigned int rate) +static void __init nuc900_clocksource_init(unsigned int rate) { unsigned int val; @@ -149,12 +149,12 @@ static void __init w90p910_clocksource_init(unsigned int rate) val |= (COUNTEN | PERIOD); __raw_writel(val, REG_TCSR1); - clocksource_w90p910.mult = - clocksource_khz2mult((rate / 1000), clocksource_w90p910.shift); - clocksource_register(&clocksource_w90p910); + clocksource_nuc900.mult = + clocksource_khz2mult((rate / 1000), clocksource_nuc900.shift); + clocksource_register(&clocksource_nuc900); } -static void __init w90p910_timer_init(void) +static void __init nuc900_timer_init(void) { struct clk *ck_ext = clk_get(NULL, "ext"); unsigned int rate; @@ -171,12 +171,12 @@ static void __init w90p910_timer_init(void) __raw_writel(RESETINT, REG_TISR); timer0_load = (rate / TICKS_PER_SEC); - setup_irq(IRQ_TIMER0, &w90p910_timer0_irq); + setup_irq(IRQ_TIMER0, &nuc900_timer0_irq); - w90p910_clocksource_init(rate); - w90p910_clockevents_init(rate); + nuc900_clocksource_init(rate); + nuc900_clockevents_init(rate); } -struct sys_timer w90x900_timer = { - .init = w90p910_timer_init, +struct sys_timer nuc900_timer = { + .init = nuc900_timer_init, }; diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6071f5882572e..937dfe4e9b12a 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c @@ -326,7 +326,7 @@ static struct platform_driver w90x900ts_driver = { .probe = w90x900ts_probe, .remove = __devexit_p(w90x900ts_remove), .driver = { - .name = "w90x900-ts", + .name = "nuc900-ts", .owner = THIS_MODULE, }, }; @@ -347,4 +347,4 @@ module_exit(w90x900ts_exit); MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); MODULE_DESCRIPTION("w90p910 touch screen driver!"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:w90p910-ts"); +MODULE_ALIAS("platform:nuc900-ts"); -- GitLab From 936fbe9efc96d40c8cdc23bba31a3beaad4f96c1 Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 21 Aug 2009 07:08:24 +0100 Subject: [PATCH 0998/1002] ARM: 5683/1: Add nuc950 platform to w90x900 Add nuc950 platform to w90x900. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/Kconfig | 15 +++++++ arch/arm/mach-w90x900/Makefile | 2 + arch/arm/mach-w90x900/mach-nuc950evb.c | 44 +++++++++++++++++++++ arch/arm/mach-w90x900/nuc950.c | 54 ++++++++++++++++++++++++++ arch/arm/mach-w90x900/nuc950.h | 28 +++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 arch/arm/mach-w90x900/mach-nuc950evb.c create mode 100644 arch/arm/mach-w90x900/nuc950.c create mode 100644 arch/arm/mach-w90x900/nuc950.h diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig index 8e4178fe5ec2b..163b8010e575c 100644 --- a/arch/arm/mach-w90x900/Kconfig +++ b/arch/arm/mach-w90x900/Kconfig @@ -5,6 +5,11 @@ config CPU_W90P910 help Support for W90P910 of Nuvoton W90X900 CPUs. +config CPU_NUC950 + bool + help + Support for NUCP950 of Nuvoton NUC900 CPUs. + menu "W90P910 Machines" config MACH_W90P910EVB @@ -16,4 +21,14 @@ config MACH_W90P910EVB endmenu +menu "NUC950 Machines" + +config MACH_W90P950EVB + bool "Nuvoton NUC950 Evaluation Board" + select CPU_NUC950 + help + Say Y here if you are using the Nuvoton NUC950EVB + +endmenu + endif diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile index e38aa328e608c..a4622b577a2c1 100644 --- a/arch/arm/mach-w90x900/Makefile +++ b/arch/arm/mach-w90x900/Makefile @@ -9,7 +9,9 @@ obj-y += clksel.o dev.o cpu.o # W90X900 CPU support files obj-$(CONFIG_CPU_W90P910) += nuc910.o +obj-$(CONFIG_CPU_NUC950) += nuc950.o # machine support obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o +obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c new file mode 100644 index 0000000000000..cef903bcccd13 --- /dev/null +++ b/arch/arm/mach-w90x900/mach-nuc950evb.c @@ -0,0 +1,44 @@ +/* + * linux/arch/arm/mach-w90x900/mach-nuc950evb.c + * + * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche + * + * Copyright (C) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach-types.h> +#include <mach/map.h> + +#include "nuc950.h" + +static void __init nuc950evb_map_io(void) +{ + nuc950_map_io(); + nuc950_init_clocks(); +} + +static void __init nuc950evb_init(void) +{ + nuc950_board_init(); +} + +MACHINE_START(W90P950EVB, "W90P950EVB") + /* Maintainer: Wan ZongShun */ + .phys_io = W90X900_PA_UART, + .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, + .boot_params = 0, + .map_io = nuc950evb_map_io, + .init_irq = nuc900_init_irq, + .init_machine = nuc950evb_init, + .timer = &nuc900_timer, +MACHINE_END diff --git a/arch/arm/mach-w90x900/nuc950.c b/arch/arm/mach-w90x900/nuc950.c new file mode 100644 index 0000000000000..149508116d18a --- /dev/null +++ b/arch/arm/mach-w90x900/nuc950.c @@ -0,0 +1,54 @@ +/* + * linux/arch/arm/mach-w90x900/nuc950.c + * + * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * NUC950 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/map.h> +#include <mach/hardware.h> +#include "cpu.h" + +/* define specific CPU platform device */ + +static struct platform_device *nuc950_dev[] __initdata = { + &nuc900_device_kpi, + &nuc900_device_fmi, +}; + +/* define specific CPU platform io map */ + +static struct map_desc nuc950evb_iodesc[] __initdata = { +}; + +/*Init NUC950 evb io*/ + +void __init nuc950_map_io(void) +{ + nuc900_map_io(nuc950evb_iodesc, ARRAY_SIZE(nuc950evb_iodesc)); +} + +/*Init NUC950 clock*/ + +void __init nuc950_init_clocks(void) +{ + nuc900_init_clocks(); +} + +/*Init NUC950 board info*/ + +void __init nuc950_board_init(void) +{ + nuc900_board_init(nuc950_dev, ARRAY_SIZE(nuc950_dev)); +} diff --git a/arch/arm/mach-w90x900/nuc950.h b/arch/arm/mach-w90x900/nuc950.h new file mode 100644 index 0000000000000..98a1148bc5ae6 --- /dev/null +++ b/arch/arm/mach-w90x900/nuc950.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-w90x900/nuc950.h + * + * Copyright (c) 2008 Nuvoton corporation + * + * Header file for NUC900 CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +struct map_desc; +struct sys_timer; + +/* core initialisation functions */ + +extern void nuc900_init_irq(void); +extern struct sys_timer nuc900_timer; + +/* extern file from nuc950.c */ + +extern void nuc950_board_init(void); +extern void nuc950_init_clocks(void); +extern void nuc950_map_io(void); -- GitLab From 8e22676e56673494a15ba95b57af21eb47d8b98a Mon Sep 17 00:00:00 2001 From: wanzongshun <mcuos.com@gmail.com> Date: Fri, 21 Aug 2009 07:09:03 +0100 Subject: [PATCH 0999/1002] ARM: 5684/1: Add nuc960 platform to w90x900 Add nuc960 platform to w90x900. Signed-off-by: Wan ZongShun <mcuos.com@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-w90x900/Kconfig | 15 +++++++ arch/arm/mach-w90x900/Makefile | 2 + arch/arm/mach-w90x900/mach-nuc960evb.c | 44 +++++++++++++++++++++ arch/arm/mach-w90x900/nuc960.c | 54 ++++++++++++++++++++++++++ arch/arm/mach-w90x900/nuc960.h | 28 +++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 arch/arm/mach-w90x900/mach-nuc960evb.c create mode 100644 arch/arm/mach-w90x900/nuc960.c create mode 100644 arch/arm/mach-w90x900/nuc960.h diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig index 163b8010e575c..69bab32a8bc25 100644 --- a/arch/arm/mach-w90x900/Kconfig +++ b/arch/arm/mach-w90x900/Kconfig @@ -10,6 +10,11 @@ config CPU_NUC950 help Support for NUCP950 of Nuvoton NUC900 CPUs. +config CPU_NUC960 + bool + help + Support for NUCP960 of Nuvoton NUC900 CPUs. + menu "W90P910 Machines" config MACH_W90P910EVB @@ -31,4 +36,14 @@ config MACH_W90P950EVB endmenu +menu "NUC960 Machines" + +config MACH_W90N960EVB + bool "Nuvoton NUC960 Evaluation Board" + select CPU_NUC960 + help + Say Y here if you are using the Nuvoton NUC960EVB + +endmenu + endif diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile index a4622b577a2c1..828c0326441e7 100644 --- a/arch/arm/mach-w90x900/Makefile +++ b/arch/arm/mach-w90x900/Makefile @@ -10,8 +10,10 @@ obj-y += clksel.o dev.o cpu.o obj-$(CONFIG_CPU_W90P910) += nuc910.o obj-$(CONFIG_CPU_NUC950) += nuc950.o +obj-$(CONFIG_CPU_NUC960) += nuc960.o # machine support obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o +obj-$(CONFIG_MACH_W90N960EVB) += mach-nuc960evb.o diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c new file mode 100644 index 0000000000000..e3a46f19f2bc5 --- /dev/null +++ b/arch/arm/mach-w90x900/mach-nuc960evb.c @@ -0,0 +1,44 @@ +/* + * linux/arch/arm/mach-w90x900/mach-nuc960evb.c + * + * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche + * + * Copyright (C) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach-types.h> +#include <mach/map.h> + +#include "nuc960.h" + +static void __init nuc960evb_map_io(void) +{ + nuc960_map_io(); + nuc960_init_clocks(); +} + +static void __init nuc960evb_init(void) +{ + nuc960_board_init(); +} + +MACHINE_START(W90N960EVB, "W90N960EVB") + /* Maintainer: Wan ZongShun */ + .phys_io = W90X900_PA_UART, + .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, + .boot_params = 0, + .map_io = nuc960evb_map_io, + .init_irq = nuc900_init_irq, + .init_machine = nuc960evb_init, + .timer = &nuc900_timer, +MACHINE_END diff --git a/arch/arm/mach-w90x900/nuc960.c b/arch/arm/mach-w90x900/nuc960.c new file mode 100644 index 0000000000000..8851a3a27ce2c --- /dev/null +++ b/arch/arm/mach-w90x900/nuc960.c @@ -0,0 +1,54 @@ +/* + * linux/arch/arm/mach-w90x900/nuc960.c + * + * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * NUC960 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/map.h> +#include <mach/hardware.h> +#include "cpu.h" + +/* define specific CPU platform device */ + +static struct platform_device *nuc960_dev[] __initdata = { + &nuc900_device_kpi, + &nuc900_device_fmi, +}; + +/* define specific CPU platform io map */ + +static struct map_desc nuc960evb_iodesc[] __initdata = { +}; + +/*Init NUC960 evb io*/ + +void __init nuc960_map_io(void) +{ + nuc900_map_io(nuc960evb_iodesc, ARRAY_SIZE(nuc960evb_iodesc)); +} + +/*Init NUC960 clock*/ + +void __init nuc960_init_clocks(void) +{ + nuc900_init_clocks(); +} + +/*Init NUC960 board info*/ + +void __init nuc960_board_init(void) +{ + nuc900_board_init(nuc960_dev, ARRAY_SIZE(nuc960_dev)); +} diff --git a/arch/arm/mach-w90x900/nuc960.h b/arch/arm/mach-w90x900/nuc960.h new file mode 100644 index 0000000000000..f0c07cbe3a823 --- /dev/null +++ b/arch/arm/mach-w90x900/nuc960.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-w90x900/nuc960.h + * + * Copyright (c) 2008 Nuvoton corporation + * + * Header file for NUC900 CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +struct map_desc; +struct sys_timer; + +/* core initialisation functions */ + +extern void nuc900_init_irq(void); +extern struct sys_timer nuc900_timer; + +/* extern file from nuc960.c */ + +extern void nuc960_board_init(void); +extern void nuc960_init_clocks(void); +extern void nuc960_map_io(void); -- GitLab From d656f07a7405e788e1275d0238b67f593615f2bb Mon Sep 17 00:00:00 2001 From: sedji gaouaou <sedji.gaouaou@atmel.com> Date: Thu, 6 Aug 2009 15:20:22 +0100 Subject: [PATCH 1000/1002] ARM: 5640/1: This patch modifies the support of AC97 on the at91sam9263 ek board This patch modifies the support of AC97 on the at91sam9263 ek board, so it would share the code with AVR32. Plus it removes a typo in at91sam9263_devices.c. Signed-off-by: Sedji Gaouaou <sedji.gaouaou@atmel.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/at91sam9263_devices.c | 14 +++++++------- arch/arm/mach-at91/board-sam9263ek.c | 2 +- arch/arm/mach-at91/include/mach/board.h | 6 ++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index b7f2332423156..55719a974276e 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -707,9 +707,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) * AC97 * -------------------------------------------------------------------- */ -#if defined(CONFIG_SND_AT91_AC97) || defined(CONFIG_SND_AT91_AC97_MODULE) +#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE) static u64 ac97_dmamask = DMA_BIT_MASK(32); -static struct atmel_ac97_data ac97_data; +static struct ac97c_platform_data ac97_data; static struct resource ac97_resources[] = { [0] = { @@ -725,8 +725,8 @@ static struct resource ac97_resources[] = { }; static struct platform_device at91sam9263_ac97_device = { - .name = "ac97c", - .id = 1, + .name = "atmel_ac97c", + .id = 0, .dev = { .dma_mask = &ac97_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), @@ -736,7 +736,7 @@ static struct platform_device at91sam9263_ac97_device = { .num_resources = ARRAY_SIZE(ac97_resources), }; -void __init at91_add_device_ac97(struct atmel_ac97_data *data) +void __init at91_add_device_ac97(struct ac97c_platform_data *data) { if (!data) return; @@ -750,11 +750,11 @@ void __init at91_add_device_ac97(struct atmel_ac97_data *data) if (data->reset_pin) at91_set_gpio_output(data->reset_pin, 0); - ac97_data = *ek_data; + ac97_data = *data; platform_device_register(&at91sam9263_ac97_device); } #else -void __init at91_add_device_ac97(struct atmel_ac97_data *data) {} +void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 57d52528f2247..3b669b78e45b6 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -365,7 +365,7 @@ static void __init ek_add_device_buttons(void) {} /* * AC97 */ -static struct atmel_ac97_data ek_ac97_data = { +static struct ac97c_platform_data ek_ac97_data = { .reset_pin = AT91_PIN_PA13, }; diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 74801d275cdc5..13f27a4b882d1 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -37,6 +37,7 @@ #include <linux/leds.h> #include <linux/spi/spi.h> #include <linux/usb/atmel_usba_udc.h> +#include <sound/atmel-ac97c.h> /* USB Device */ struct at91_udc_data { @@ -174,10 +175,7 @@ struct atmel_lcdfb_info; extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data); /* AC97 */ -struct atmel_ac97_data { - u8 reset_pin; /* reset */ -}; -extern void __init at91_add_device_ac97(struct atmel_ac97_data *data); +extern void __init at91_add_device_ac97(struct ac97c_platform_data *data); /* ISI */ extern void __init at91_add_device_isi(void); -- GitLab From 8c3cbd5a2b2cc244277f6089dae83f09f1e7a27b Mon Sep 17 00:00:00 2001 From: Nicolas Ferre <nicolas.ferre@atmel.com> Date: Wed, 26 Aug 2009 15:33:16 +0100 Subject: [PATCH 1001/1002] ARM: 5686/1: at91: Correct AC97 reset line in at91sam9263ek board Board code was wrongly setting up the reset pin for AC97 on at91sam9263ek. Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Andrew Victor <linux@maxim.org.za> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/mach-at91/board-sam9263ek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 3b669b78e45b6..1bf7bd4cbe13c 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -364,9 +364,9 @@ static void __init ek_add_device_buttons(void) {} /* * AC97 + * reset_pin is not connected: NRST */ static struct ac97c_platform_data ek_ac97_data = { - .reset_pin = AT91_PIN_PA13, }; -- GitLab From c1cb6b7fb5190ad55b31aa3289d48fedd288ddaa Mon Sep 17 00:00:00 2001 From: Russell King <rmk@dyn-67.arm.linux.org.uk> Date: Sat, 12 Sep 2009 12:00:17 +0100 Subject: [PATCH 1002/1002] [ARM] Update mach-types Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> --- arch/arm/tools/mach-types | 68 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 200d83a98286a..c8c55b4693428 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sat Aug 1 16:26:02 2009 +# Last update: Sat Sep 12 12:00:16 2009 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1962,7 +1962,7 @@ ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971 arm11 MACH_ARM11 ARM11 1972 cpuat9260 MACH_CPUAT9260 CPUAT9260 1973 cpupxa255 MACH_CPUPXA255 CPUPXA255 1974 -cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 +eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975 cheflux MACH_CHEFLUX CHEFLUX 1976 eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977 opcotec MACH_OPCOTEC OPCOTEC 1978 @@ -2249,14 +2249,14 @@ omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261 darwin MACH_DARWIN DARWIN 2262 oratiscomu MACH_ORATISCOMU ORATISCOMU 2263 rtsbc20 MACH_RTSBC20 RTSBC20 2264 -i780 MACH_I780 I780 2265 +sgh_i780 MACH_I780 I780 2265 gemini324 MACH_GEMINI324 GEMINI324 2266 oratislan MACH_ORATISLAN ORATISLAN 2267 oratisalog MACH_ORATISALOG ORATISALOG 2268 oratismadi MACH_ORATISMADI ORATISMADI 2269 oratisot16 MACH_ORATISOT16 ORATISOT16 2270 oratisdesk MACH_ORATISDESK ORATISDESK 2271 -v2p_ca9 MACH_V2P_CA9 V2P_CA9 2272 +v2_ca9 MACH_V2P_CA9 V2P_CA9 2272 sintexo MACH_SINTEXO SINTEXO 2273 cm3389 MACH_CM3389 CM3389 2274 omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275 @@ -2349,3 +2349,63 @@ openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361 hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362 wayland MACH_WAYLAND WAYLAND 2363 acnbsx102 MACH_ACNBSX102 ACNBSX102 2364 +hwat91 MACH_HWAT91 HWAT91 2365 +at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366 +csb732 MACH_CSB732 CSB732 2367 +u8500 MACH_U8500 U8500 2368 +huqiu MACH_HUQIU HUQIU 2369 +mx51_kunlun MACH_MX51_KUNLUN MX51_KUNLUN 2370 +pmt1g MACH_PMT1G PMT1G 2371 +htcelf MACH_HTCELF HTCELF 2372 +armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373 +armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374 +u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375 +csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376 +dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377 +hy9307 MACH_HY9307 HY9307 2378 +aspire_easystore MACH_A_ES A_ES 2379 +davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380 +agama9263 MACH_AGAMA9263 AGAMA9263 2381 +marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382 +flint MACH_FLINT FLINT 2383 +tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384 +sch_m490 MACH_SCH_M490 SCH_M490 2386 +rbl01 MACH_RBL01 RBL01 2387 +omnifi MACH_OMNIFI OMNIFI 2388 +otavalo MACH_OTAVALO OTAVALO 2389 +sienna MACH_SIENNA SIENNA 2390 +htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391 +htc_opal MACH_HTC_OPAL HTC_OPAL 2392 +touchbook MACH_TOUCHBOOK TOUCHBOOK 2393 +latte MACH_LATTE LATTE 2394 +xa200 MACH_XA200 XA200 2395 +nimrod MACH_NIMROD NIMROD 2396 +cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397 +cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398 +tk71 MACH_TK71 TK71 2399 +comham3525 MACH_COMHAM3525 COMHAM3525 2400 +mx31erebus MACH_MX31EREBUS MX31EREBUS 2401 +mcardmx27 MACH_MCARDMX27 MCARDMX27 2402 +paradise MACH_PARADISE PARADISE 2403 +tide MACH_TIDE TIDE 2404 +wzl2440 MACH_WZL2440 WZL2440 2405 +sdrdemo MACH_SDRDEMO SDRDEMO 2406 +ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407 +ecmimg20 MACH_ECMIMG20 ECMIMG20 2408 +omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409 +halo MACH_HALO HALO 2410 +huangshan MACH_HUANGSHAN HUANGSHAN 2411 +vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412 +raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413 +raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414 +raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415 +multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416 +multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417 +tnetv107x MACH_TNETV107X TNETV107X 2418 +snake MACH_SNAKE SNAKE 2419 +cwmx27 MACH_CWMX27 CWMX27 2420 +sch_m480 MACH_SCH_M480 SCH_M480 2421 +platypus MACH_PLATYPUS PLATYPUS 2422 +pss2 MACH_PSS2 PSS2 2423 +davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424 +str9100 MACH_STR9100 STR9100 2425 -- GitLab