diff --git a/[refs] b/[refs] index 59142df42c86..a1001792d6c4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a4a47bc03fe520e95e0c4212bf97c86545fb14f9 +refs/heads/master: f07852d6442c46c50b59c7e2acc8a1b291f9ab6d diff --git a/trunk/Documentation/dontdiff b/trunk/Documentation/dontdiff index d9bcffd59433..3ad6acead949 100644 --- a/trunk/Documentation/dontdiff +++ b/trunk/Documentation/dontdiff @@ -69,6 +69,7 @@ av_permissions.h bbootsect bin2c binkernel.spec +binoffset bootsect bounds.h bsetup diff --git a/trunk/Documentation/lguest/lguest.c b/trunk/Documentation/lguest/lguest.c index 3119f5db75bd..42208511b5c0 100644 --- a/trunk/Documentation/lguest/lguest.c +++ b/trunk/Documentation/lguest/lguest.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/Documentation/networking/ip-sysctl.txt b/trunk/Documentation/networking/ip-sysctl.txt index e87f3cdc8a6a..006b39dec87d 100644 --- a/trunk/Documentation/networking/ip-sysctl.txt +++ b/trunk/Documentation/networking/ip-sysctl.txt @@ -1074,10 +1074,10 @@ regen_max_retry - INTEGER Default: 5 max_addresses - INTEGER - Maximum number of autoconfigured addresses per interface. Setting - to zero disables the limitation. It is not recommended to set this - value too large (or to zero) because it would be an easy way to - crash the kernel by allowing too many addresses to be created. + Number of maximum addresses per interface. 0 disables limitation. + It is recommended not set too large value (or 0) because it would + be too easy way to crash kernel to allow to create too much of + autoconfigured addresses. Default: 16 disable_ipv6 - BOOLEAN diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 317ed38826d7..c95f727236e1 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2393,12 +2393,6 @@ L: linuxppc-dev@ozlabs.org S: Odd Fixes F: drivers/char/hvc_* -VIRTIO CONSOLE DRIVER -M: Amit Shah -L: virtualization@lists.linux-foundation.org -S: Maintained -F: drivers/char/virtio_console.c - GSPCA FINEPIX SUBDRIVER M: Frank Zago L: linux-media@vger.kernel.org @@ -3495,9 +3489,9 @@ S: Maintained F: drivers/net/wireless/libertas/ MARVELL MV643XX ETHERNET DRIVER -M: Lennert Buytenhek +M: Lennert Buytenhek L: netdev@vger.kernel.org -S: Maintained +S: Supported F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h diff --git a/trunk/Makefile b/trunk/Makefile index 1b24895212d8..12b1aa1103ee 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 33 -EXTRAVERSION = +EXTRAVERSION = -rc8 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* diff --git a/trunk/arch/ia64/sn/kernel/setup.c b/trunk/arch/ia64/sn/kernel/setup.c index e456f062f241..ece1bf994499 100644 --- a/trunk/arch/ia64/sn/kernel/setup.c +++ b/trunk/arch/ia64/sn/kernel/setup.c @@ -71,7 +71,7 @@ EXPORT_SYMBOL(sn_rtc_cycles_per_second); DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info); EXPORT_PER_CPU_SYMBOL(__sn_hub_info); -DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_COMPACT_NODES]); +DEFINE_PER_CPU(short [MAX_COMPACT_NODES], __sn_cnodeid_to_nasid); EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); diff --git a/trunk/arch/microblaze/Kconfig b/trunk/arch/microblaze/Kconfig index b008168ae946..cd5837e298b2 100644 --- a/trunk/arch/microblaze/Kconfig +++ b/trunk/arch/microblaze/Kconfig @@ -130,7 +130,6 @@ config CMDLINE_FORCE config OF def_bool y - select OF_FLATTREE config PROC_DEVICETREE bool "Support for device tree in /proc" diff --git a/trunk/arch/microblaze/include/asm/io.h b/trunk/arch/microblaze/include/asm/io.h index 267c7c779e53..fc9997b73c09 100644 --- a/trunk/arch/microblaze/include/asm/io.h +++ b/trunk/arch/microblaze/include/asm/io.h @@ -217,7 +217,7 @@ static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size, * Little endian */ -#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (a)) +#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (a)); #define out_le16(a, v) __raw_writew(__cpu_to_le16(v), (a)) #define in_le32(a) __le32_to_cpu(__raw_readl(a)) diff --git a/trunk/arch/microblaze/include/asm/prom.h b/trunk/arch/microblaze/include/asm/prom.h index 03f45a963204..ef3ec1d6ceb3 100644 --- a/trunk/arch/microblaze/include/asm/prom.h +++ b/trunk/arch/microblaze/include/asm/prom.h @@ -26,11 +26,31 @@ #include #include +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strncasecmp((s1), (s2), (l)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) + +extern struct device_node *of_chosen; + #define HAVE_ARCH_DEVTREE_FIXUPS +extern struct device_node *allnodes; /* temporary while merging */ +extern rwlock_t devtree_lock; /* temporary while merging */ + +/* For updating the device tree at runtime */ +extern void of_attach_node(struct device_node *); +extern void of_detach_node(struct device_node *); + /* Other Prototypes */ extern int early_uartlite_console(void); +extern struct resource *request_OF_resource(struct device_node *node, + int index, const char *name_postfix); +extern int release_OF_resource(struct device_node *node, int index); + /* * OF address retreival & translation */ diff --git a/trunk/arch/microblaze/kernel/cpu/cache.c b/trunk/arch/microblaze/kernel/cpu/cache.c index 2a56bccce4e0..d9d63831cc2f 100644 --- a/trunk/arch/microblaze/kernel/cpu/cache.c +++ b/trunk/arch/microblaze/kernel/cpu/cache.c @@ -172,15 +172,16 @@ do { \ /* It is used only first parameter for OP - for wic, wdc */ #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ do { \ - int volatile temp; \ - BUG_ON(end - start <= 0); \ + int step = -line_length; \ + int count = end - start; \ + BUG_ON(count <= 0); \ \ - __asm__ __volatile__ (" 1: " #op " %1, r0; \ - cmpu %0, %1, %2; \ - bgtid %0, 1b; \ - addk %1, %1, %3; \ - " : : "r" (temp), "r" (start), "r" (end),\ - "r" (line_length) : "memory"); \ + __asm__ __volatile__ (" 1: addk %0, %0, %1; \ + " #op " %0, r0; \ + bgtid %1, 1b; \ + addk %1, %1, %2; \ + " : : "r" (start), "r" (count), \ + "r" (step) : "memory"); \ } while (0); static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) @@ -312,6 +313,16 @@ static void __invalidate_dcache_all_wb(void) pr_debug("%s\n", __func__); CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc.clear) + +#if 0 + unsigned int i; + + pr_debug("%s\n", __func__); + + /* Just loop through cache size and invalidate it */ + for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) + __invalidate_dcache(0, i); +#endif } static void __invalidate_dcache_range_wb(unsigned long start, diff --git a/trunk/arch/microblaze/kernel/of_platform.c b/trunk/arch/microblaze/kernel/of_platform.c index 1c6d684996d7..acf4574d0f18 100644 --- a/trunk/arch/microblaze/kernel/of_platform.c +++ b/trunk/arch/microblaze/kernel/of_platform.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(of_find_device_by_node); static int of_dev_phandle_match(struct device *dev, void *data) { phandle *ph = data; - return to_of_device(dev)->node->phandle == *ph; + return to_of_device(dev)->node->linux_phandle == *ph; } struct of_device *of_find_device_by_phandle(phandle ph) diff --git a/trunk/arch/microblaze/kernel/prom.c b/trunk/arch/microblaze/kernel/prom.c index a15ef6d67ca9..b817df172aa9 100644 --- a/trunk/arch/microblaze/kernel/prom.c +++ b/trunk/arch/microblaze/kernel/prom.c @@ -42,21 +42,698 @@ #include #include -void __init early_init_dt_scan_chosen_arch(unsigned long node) +static int __initdata dt_root_addr_cells; +static int __initdata dt_root_size_cells; + +typedef u32 cell_t; + +static struct boot_param_header *initial_boot_params; + +/* export that to outside world */ +struct device_node *of_chosen; + +static inline char *find_flat_dt_string(u32 offset) +{ + return ((char *)initial_boot_params) + + initial_boot_params->off_dt_strings + offset; +} + +/** + * This function is used to scan the flattened device-tree, it is + * used to extract the memory informations at boot before we can + * unflatten the tree + */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + int rc = 0; + int depth = -1; + + do { + u32 tag = *((u32 *)p); + char *pathp; + + p += 4; + if (tag == OF_DT_END_NODE) { + depth--; + continue; + } + if (tag == OF_DT_NOP) + continue; + if (tag == OF_DT_END) + break; + if (tag == OF_DT_PROP) { + u32 sz = *((u32 *)p); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + p += sz; + p = _ALIGN(p, 4); + continue; + } + if (tag != OF_DT_BEGIN_NODE) { + printk(KERN_WARNING "Invalid tag %x scanning flattened" + " device tree !\n", tag); + return -EINVAL; + } + depth++; + pathp = (char *)p; + p = _ALIGN(p + strlen(pathp) + 1, 4); + if ((*pathp) == '/') { + char *lp, *np; + for (lp = NULL, np = pathp; *np; np++) + if ((*np) == '/') + lp = np+1; + if (lp != NULL) + pathp = lp; + } + rc = it(p, pathp, depth, data); + if (rc != 0) + break; + } while (1); + + return rc; +} + +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while (*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + +/** + * This function can be used within scan_flattened_dt callback to get + * access to properties + */ +void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) +{ + unsigned long p = node; + + do { + u32 tag = *((u32 *)p); + u32 sz, noff; + const char *nstr; + + p += 4; + if (tag == OF_DT_NOP) + continue; + if (tag != OF_DT_PROP) + return NULL; + + sz = *((u32 *)p); + noff = *((u32 *)(p + 4)); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + + nstr = find_flat_dt_string(noff); + if (nstr == NULL) { + printk(KERN_WARNING "Can't find property index" + " name !\n"); + return NULL; + } + if (strcmp(name, nstr) == 0) { + if (size) + *size = sz; + return (void *)p; + } + p += sz; + p = _ALIGN(p, 4); + } while (1); +} + +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char *cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + +static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, + unsigned long align) +{ + void *res; + + *mem = _ALIGN(*mem, align); + res = (void *)*mem; + *mem += size; + + return res; +} + +static unsigned long __init unflatten_dt_node(unsigned long mem, + unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp, + unsigned long fpsize) +{ + struct device_node *np; + struct property *pp, **prev_pp = NULL; + char *pathp; + u32 tag; + unsigned int l, allocl; + int has_name = 0; + int new_format = 0; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_BEGIN_NODE) { + printk("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + pathp = (char *)*p; + l = allocl = strlen(pathp) + 1; + *p = _ALIGN(*p + l, 4); + + /* version 0x10 has a more compact unit name here instead of the full + * path. we accumulate the full path size using "fpsize", we'll rebuild + * it later. We detect this because the first character of the name is + * not '/'. + */ + if ((*pathp) != '/') { + new_format = 1; + if (fpsize == 0) { + /* root node: special case. fpsize accounts for path + * plus terminating zero. root node only has '/', so + * fpsize should be 2, but we want to avoid the first + * level nodes to have two '/' so we use fpsize 1 here + */ + fpsize = 1; + allocl = 2; + } else { + /* account for '/' and path size minus terminal 0 + * already in 'l' + */ + fpsize += l; + allocl = fpsize; + } + } + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, + __alignof__(struct device_node)); + if (allnextpp) { + memset(np, 0, sizeof(*np)); + np->full_name = ((char *)np) + sizeof(struct device_node); + if (new_format) { + char *p2 = np->full_name; + /* rebuild full path for new format */ + if (dad && dad->parent) { + strcpy(p2, dad->full_name); +#ifdef DEBUG + if ((strlen(p2) + l + 1) != allocl) { + pr_debug("%s: p: %d, l: %d, a: %d\n", + pathp, (int)strlen(p2), + l, allocl); + } +#endif + p2 += strlen(p2); + } + *(p2++) = '/'; + memcpy(p2, pathp, l); + } else + memcpy(np->full_name, pathp, l); + prev_pp = &np->properties; + **allnextpp = np; + *allnextpp = &np->allnext; + if (dad != NULL) { + np->parent = dad; + /* we temporarily use the next field as `last_child'*/ + if (dad->next == NULL) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + kref_init(&np->kref); + } + while (1) { + u32 sz, noff; + char *pname; + + tag = *((u32 *)(*p)); + if (tag == OF_DT_NOP) { + *p += 4; + continue; + } + if (tag != OF_DT_PROP) + break; + *p += 4; + sz = *((u32 *)(*p)); + noff = *((u32 *)((*p) + 4)); + *p += 8; + if (initial_boot_params->version < 0x10) + *p = _ALIGN(*p, sz >= 8 ? 8 : 4); + + pname = find_flat_dt_string(noff); + if (pname == NULL) { + printk(KERN_INFO + "Can't find property name in list !\n"); + break; + } + if (strcmp(pname, "name") == 0) + has_name = 1; + l = strlen(pname) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property), + __alignof__(struct property)); + if (allnextpp) { + if (strcmp(pname, "linux,phandle") == 0) { + np->node = *((u32 *)*p); + if (np->linux_phandle == 0) + np->linux_phandle = np->node; + } + if (strcmp(pname, "ibm,phandle") == 0) + np->linux_phandle = *((u32 *)*p); + pp->name = pname; + pp->length = sz; + pp->value = (void *)*p; + *prev_pp = pp; + prev_pp = &pp->next; + } + *p = _ALIGN((*p) + sz, 4); + } + /* with version 0x10 we may not have the name property, recreate + * it here from the unit name if absent + */ + if (!has_name) { + char *p1 = pathp, *ps = pathp, *pa = NULL; + int sz; + + while (*p1) { + if ((*p1) == '@') + pa = p1; + if ((*p1) == '/') + ps = p1 + 1; + p1++; + } + if (pa < ps) + pa = p1; + sz = (pa - ps) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, + __alignof__(struct property)); + if (allnextpp) { + pp->name = "name"; + pp->length = sz; + pp->value = pp + 1; + *prev_pp = pp; + prev_pp = &pp->next; + memcpy(pp->value, ps, sz - 1); + ((char *)pp->value)[sz - 1] = 0; + pr_debug("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); + } + } + if (allnextpp) { + *prev_pp = NULL; + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); + + if (!np->name) + np->name = ""; + if (!np->type) + np->type = ""; + } + while (tag == OF_DT_BEGIN_NODE) { + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); + tag = *((u32 *)(*p)); + } + if (tag != OF_DT_END_NODE) { + printk(KERN_INFO "Weird tag at end of node: %x\n", tag); + return mem; + } + *p += 4; + return mem; +} + +/** + * unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used (this used to be done by finish_device_tree) + */ +void __init unflatten_device_tree(void) +{ + unsigned long start, mem, size; + struct device_node **allnextp = &allnodes; + + pr_debug(" -> unflatten_device_tree()\n"); + + /* First pass, scan for size */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + size = unflatten_dt_node(0, &start, NULL, NULL, 0); + size = (size | 3) + 1; + + pr_debug(" size is %lx, allocating...\n", size); + + /* Allocate memory for the expanded device tree */ + mem = lmb_alloc(size + 4, __alignof__(struct device_node)); + mem = (unsigned long) __va(mem); + + ((u32 *)mem)[size / 4] = 0xdeadbeef; + + pr_debug(" unflattening %lx...\n", mem); + + /* Second pass, do actual unflattening */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + unflatten_dt_node(mem, &start, NULL, &allnextp, 0); + if (*((u32 *)start) != OF_DT_END) + printk(KERN_WARNING "Weird tag at end of tree: %08x\n", + *((u32 *)start)); + if (((u32 *)mem)[size / 4] != 0xdeadbeef) + printk(KERN_WARNING "End of tree marker overwritten: %08x\n", + ((u32 *)mem)[size / 4]); + *allnextp = NULL; + + /* Get pointer to OF "/chosen" node for use everywhere */ + of_chosen = of_find_node_by_path("/chosen"); + if (of_chosen == NULL) + of_chosen = of_find_node_by_path("/chosen@0"); + + pr_debug(" <- unflatten_device_tree()\n"); +} + +#define early_init_dt_scan_drconf_memory(node) 0 + +static int __init early_init_dt_scan_cpus(unsigned long node, + const char *uname, int depth, + void *data) +{ + static int logical_cpuid; + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const u32 *intserv; + int i, nthreads; + int found = 0; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + /* Get physical cpuid */ + intserv = of_get_flat_dt_prop(node, "reg", NULL); + nthreads = 1; + + /* + * Now see if any of these threads match our boot cpu. + * NOTE: This must match the parsing done in smp_setup_cpu_maps. + */ + for (i = 0; i < nthreads; i++) { + /* + * version 2 of the kexec param format adds the phys cpuid of + * booted proc. + */ + if (initial_boot_params && initial_boot_params->version >= 2) { + if (intserv[i] == + initial_boot_params->boot_cpuid_phys) { + found = 1; + break; + } + } else { + /* + * Check if it's the boot-cpu, set it's hw index now, + * unfortunately this format did not support booting + * off secondary threads. + */ + if (of_get_flat_dt_prop(node, + "linux,boot-cpu", NULL) != NULL) { + found = 1; + break; + } + } + +#ifdef CONFIG_SMP + /* logical cpu id is always 0 on UP kernels */ + logical_cpuid++; +#endif + } + + if (found) { + pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid, + intserv[i]); + boot_cpuid = logical_cpuid; + } + + return 0; +} + +#ifdef CONFIG_BLK_DEV_INITRD +static void __init early_init_dt_check_for_initrd(unsigned long node) +{ + unsigned long l; + u32 *prop; + + pr_debug("Looking for initrd properties... "); + + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long) + __va((u32)of_read_ulong(prop, l/4)); + + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long) + __va((u32)of_read_ulong(prop, 1/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + + pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", + initrd_start, initrd_end); +} +#else +static inline void early_init_dt_check_for_initrd(unsigned long node) +{ +} +#endif /* CONFIG_BLK_DEV_INITRD */ + +static int __init early_init_dt_scan_chosen(unsigned long node, + const char *uname, int depth, void *data) +{ + unsigned long l; + char *p; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + + if (depth != 1 || + (strcmp(uname, "chosen") != 0 && + strcmp(uname, "chosen@0") != 0)) + return 0; + +#ifdef CONFIG_KEXEC + lprop = (u64 *)of_get_flat_dt_prop(node, + "linux,crashkernel-base", NULL); + if (lprop) + crashk_res.start = *lprop; + + lprop = (u64 *)of_get_flat_dt_prop(node, + "linux,crashkernel-size", NULL); + if (lprop) + crashk_res.end = crashk_res.start + *lprop - 1; +#endif + + early_init_dt_check_for_initrd(node); + + /* Retreive command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); + +#ifdef CONFIG_CMDLINE +#ifndef CONFIG_CMDLINE_FORCE + if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) +#endif + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif /* CONFIG_CMDLINE */ + + pr_debug("Command line is: %s\n", cmd_line); + + /* break now */ + return 1; +} + +static int __init early_init_dt_scan_root(unsigned long node, + const char *uname, int depth, void *data) +{ + u32 *prop; + + if (depth != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + dt_root_size_cells = (prop == NULL) ? 1 : *prop; + pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); + + /* break now */ + return 1; +} + +static u64 __init dt_mem_next_cell(int s, cell_t **cellp) { - /* No Microblaze specific code here */ + cell_t *p = *cellp; + + *cellp = p + s; + return of_read_number(p, s); } -void __init early_init_dt_add_memory_arch(u64 base, u64 size) +static int __init early_init_dt_scan_memory(unsigned long node, + const char *uname, int depth, void *data) { - lmb_add(base, size); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + cell_t *reg, *endp; + unsigned long l; + + /* Look for the ibm,dynamic-reconfiguration-memory node */ +/* if (depth == 1 && + strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) + return early_init_dt_scan_drconf_memory(node); +*/ + /* We are scanning "memory" nodes only */ + if (type == NULL) { + /* + * The longtrail doesn't have a device_type on the + * /memory node, so look for the node called /memory@0. + */ + if (depth != 1 || strcmp(uname, "memory@0") != 0) + return 0; + } else if (strcmp(type, "memory") != 0) + return 0; + + reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); + if (reg == NULL) + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); + if (reg == NULL) + return 0; + + endp = reg + (l / sizeof(cell_t)); + + pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", + uname, l, reg[0], reg[1], reg[2], reg[3]); + + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + u64 base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + + if (size == 0) + continue; + pr_debug(" - %llx , %llx\n", (unsigned long long)base, + (unsigned long long)size); + + lmb_add(base, size); + } + return 0; } -u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +#ifdef CONFIG_PHYP_DUMP +/** + * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg + * + * Function to find the largest size we need to reserve + * during early boot process. + * + * It either looks for boot param and returns that OR + * returns larger of 256 or 5% rounded down to multiples of 256MB. + * + */ +static inline unsigned long phyp_dump_calculate_reserve_size(void) { - return lmb_alloc(size, align); + unsigned long tmp; + + if (phyp_dump_info->reserve_bootvar) + return phyp_dump_info->reserve_bootvar; + + /* divide by 20 to get 5% of value */ + tmp = lmb_end_of_DRAM(); + do_div(tmp, 20); + + /* round it down in multiples of 256 */ + tmp = tmp & ~0x0FFFFFFFUL; + + return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END); } +/** + * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory + * + * This routine may reserve memory regions in the kernel only + * if the system is supported and a dump was taken in last + * boot instance or if the hardware is supported and the + * scratch area needs to be setup. In other instances it returns + * without reserving anything. The memory in case of dump being + * active is freed when the dump is collected (by userland tools). + */ +static void __init phyp_dump_reserve_mem(void) +{ + unsigned long base, size; + unsigned long variable_reserve_size; + + if (!phyp_dump_info->phyp_dump_configured) { + printk(KERN_ERR "Phyp-dump not supported on this hardware\n"); + return; + } + + if (!phyp_dump_info->phyp_dump_at_boot) { + printk(KERN_INFO "Phyp-dump disabled at boot time\n"); + return; + } + + variable_reserve_size = phyp_dump_calculate_reserve_size(); + + if (phyp_dump_info->phyp_dump_is_active) { + /* Reserve *everything* above RMR.Area freed by userland tools*/ + base = variable_reserve_size; + size = lmb_end_of_DRAM() - base; + + /* XXX crashed_ram_end is wrong, since it may be beyond + * the memory_limit, it will need to be adjusted. */ + lmb_reserve(base, size); + + phyp_dump_info->init_reserve_start = base; + phyp_dump_info->init_reserve_size = size; + } else { + size = phyp_dump_info->cpu_state_size + + phyp_dump_info->hpte_region_size + + variable_reserve_size; + base = lmb_end_of_DRAM() - size; + lmb_reserve(base, size); + phyp_dump_info->init_reserve_start = base; + phyp_dump_info->init_reserve_size = size; + } +} +#else +static inline void __init phyp_dump_reserve_mem(void) {} +#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ + #ifdef CONFIG_EARLY_PRINTK /* MS this is Microblaze specifig function */ static int __init early_init_dt_scan_serial(unsigned long node, @@ -98,6 +775,11 @@ void __init early_init_devtree(void *params) /* Setup flat device-tree pointer */ initial_boot_params = params; +#ifdef CONFIG_PHYP_DUMP + /* scan tree to see if dump occured during last boot */ + of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); +#endif + /* Retrieve various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... @@ -117,18 +799,33 @@ void __init early_init_devtree(void *params) pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size()); + pr_debug("Scanning CPUs ...\n"); + + /* Retreive CPU related informations from the flat tree + * (altivec support, boot CPU ID, ...) + */ + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); + pr_debug(" <- early_init_devtree()\n"); } -#ifdef CONFIG_BLK_DEV_INITRD -void __init early_init_dt_setup_initrd_arch(unsigned long start, - unsigned long end) +/** + * Indicates whether the root node has a given value in its + * compatible property. + */ +int machine_is_compatible(const char *compat) { - initrd_start = (unsigned long)__va(start); - initrd_end = (unsigned long)__va(end); - initrd_below_start_ok = 1; + struct device_node *root; + int rc = 0; + + root = of_find_node_by_path("/"); + if (root) { + rc = of_device_is_compatible(root, compat); + of_node_put(root); + } + return rc; } -#endif +EXPORT_SYMBOL(machine_is_compatible); /******* * @@ -141,6 +838,273 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start, * *******/ +/** + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + read_lock(&devtree_lock); + for (np = allnodes; np != NULL; np = np->allnext) + if (np->linux_phandle == handle) + break; + of_node_get(np); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +/** + * of_node_get - Increment refcount of a node + * @node: Node to inc refcount, NULL is supported to + * simplify writing of callers + * + * Returns node. + */ +struct device_node *of_node_get(struct device_node *node) +{ + if (node) + kref_get(&node->kref); + return node; +} +EXPORT_SYMBOL(of_node_get); + +static inline struct device_node *kref_to_device_node(struct kref *kref) +{ + return container_of(kref, struct device_node, kref); +} + +/** + * of_node_release - release a dynamically allocated node + * @kref: kref element of the node to be released + * + * In of_node_put() this function is passed to kref_put() + * as the destructor. + */ +static void of_node_release(struct kref *kref) +{ + struct device_node *node = kref_to_device_node(kref); + struct property *prop = node->properties; + + /* We should never be releasing nodes that haven't been detached. */ + if (!of_node_check_flag(node, OF_DETACHED)) { + printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n", + node->full_name); + dump_stack(); + kref_init(&node->kref); + return; + } + + if (!of_node_check_flag(node, OF_DYNAMIC)) + return; + + while (prop) { + struct property *next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + prop = next; + + if (!prop) { + prop = node->deadprops; + node->deadprops = NULL; + } + } + kfree(node->full_name); + kfree(node->data); + kfree(node); +} + +/** + * of_node_put - Decrement refcount of a node + * @node: Node to dec refcount, NULL is supported to + * simplify writing of callers + * + */ +void of_node_put(struct device_node *node) +{ + if (node) + kref_put(&node->kref, of_node_release); +} +EXPORT_SYMBOL(of_node_put); + +/* + * Plug a device node into the tree and global list. + */ +void of_attach_node(struct device_node *np) +{ + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + np->sibling = np->parent->child; + np->allnext = allnodes; + np->parent->child = np; + allnodes = np; + write_unlock_irqrestore(&devtree_lock, flags); +} + +/* + * "Unplug" a node from the device tree. The caller must hold + * a reference to the node. The memory associated with the node + * is not freed until its refcount goes to zero. + */ +void of_detach_node(struct device_node *np) +{ + struct device_node *parent; + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + + parent = np->parent; + if (!parent) + goto out_unlock; + + if (allnodes == np) + allnodes = np->allnext; + else { + struct device_node *prev; + for (prev = allnodes; + prev->allnext != np; + prev = prev->allnext) + ; + prev->allnext = np->allnext; + } + + if (parent->child == np) + parent->child = np->sibling; + else { + struct device_node *prevsib; + for (prevsib = np->parent->child; + prevsib->sibling != np; + prevsib = prevsib->sibling) + ; + prevsib->sibling = np->sibling; + } + + of_node_set_flag(np, OF_DETACHED); + +out_unlock: + write_unlock_irqrestore(&devtree_lock, flags); +} + +/* + * Add a property to a node + */ +int prom_add_property(struct device_node *np, struct property *prop) +{ + struct property **next; + unsigned long flags; + + prop->next = NULL; + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock_irqrestore(&devtree_lock, flags); + return -1; + } + next = &(*next)->next; + } + *next = prop; + write_unlock_irqrestore(&devtree_lock, flags); + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Remove a property from a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, so it won't be found any more. + */ +int prom_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == prop) { + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to remove the proc node as well */ + if (np->pde) + proc_device_tree_remove_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Update a property in a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, and add the new property to the + * property list + */ +int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_update_prop(np->pde, newprop, oldprop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) static struct debugfs_blob_wrapper flat_dt_blob; diff --git a/trunk/arch/mips/bcm47xx/prom.c b/trunk/arch/mips/bcm47xx/prom.c index 29d3cbf9555f..c51405e57921 100644 --- a/trunk/arch/mips/bcm47xx/prom.c +++ b/trunk/arch/mips/bcm47xx/prom.c @@ -141,14 +141,6 @@ static __init void prom_init_mem(void) break; } - /* Ignoring the last page when ddr size is 128M. Cached - * accesses to last page is causing the processor to prefetch - * using address above 128M stepping out of the ddr address - * space. - */ - if (mem == 0x8000000) - mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } diff --git a/trunk/arch/mips/mm/highmem.c b/trunk/arch/mips/mm/highmem.c index 127d732474bf..e274fda329f4 100644 --- a/trunk/arch/mips/mm/highmem.c +++ b/trunk/arch/mips/mm/highmem.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index f388dc68f605..524d9352f17e 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -18,6 +18,7 @@ config PARISC select BUG select HAVE_PERF_EVENTS select GENERIC_ATOMIC64 if !64BIT + select HAVE_ARCH_TRACEHOOK 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/trunk/arch/parisc/kernel/pci.c b/trunk/arch/parisc/kernel/pci.c index 9e74bfe071dc..f7064abc3bb6 100644 --- a/trunk/arch/parisc/kernel/pci.c +++ b/trunk/arch/parisc/kernel/pci.c @@ -18,6 +18,7 @@ #include #include +#include /* for L1_CACHE_BYTES */ #include #define DEBUG_RESOURCES 0 @@ -122,10 +123,6 @@ static int __init pcibios_init(void) } else { printk(KERN_WARNING "pci_bios != NULL but init() is!\n"); } - - /* Set the CLS for PCI as early as possible. */ - pci_cache_line_size = pci_dfl_cache_line_size; - return 0; } @@ -174,7 +171,7 @@ void pcibios_set_master(struct pci_dev *dev) ** upper byte is PCI_LATENCY_TIMER. */ pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, - (0x80 << 8) | pci_cache_line_size); + (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32))); } diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 50c9af43e017..ba3948c70072 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -173,7 +173,6 @@ config PPC_OF config OF def_bool y - select OF_FLATTREE config PPC_UDBG_16550 bool diff --git a/trunk/arch/powerpc/include/asm/prom.h b/trunk/arch/powerpc/include/asm/prom.h index ddd408a93b5a..2ab9cbd98826 100644 --- a/trunk/arch/powerpc/include/asm/prom.h +++ b/trunk/arch/powerpc/include/asm/prom.h @@ -23,8 +23,21 @@ #include #include +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) + +extern struct device_node *of_chosen; + #define HAVE_ARCH_DEVTREE_FIXUPS +/* For updating the device tree at runtime */ +extern void of_attach_node(struct device_node *); +extern void of_detach_node(struct device_node *); + #ifdef CONFIG_PPC32 /* * PCI <-> OF matching functions @@ -39,6 +52,11 @@ extern struct device_node* pci_device_to_OF_node(struct pci_dev *); extern void pci_create_OF_bus_map(void); #endif +extern struct resource *request_OF_resource(struct device_node* node, + int index, const char* name_postfix); +extern int release_OF_resource(struct device_node* node, int index); + + /* * OF address retreival & translation */ diff --git a/trunk/arch/powerpc/kernel/of_platform.c b/trunk/arch/powerpc/kernel/of_platform.c index 666d08db319e..1a4fc0d11a03 100644 --- a/trunk/arch/powerpc/kernel/of_platform.c +++ b/trunk/arch/powerpc/kernel/of_platform.c @@ -214,7 +214,7 @@ EXPORT_SYMBOL(of_find_device_by_node); static int of_dev_phandle_match(struct device *dev, void *data) { phandle *ph = data; - return to_of_device(dev)->node->phandle == *ph; + return to_of_device(dev)->node->linux_phandle == *ph; } struct of_device *of_find_device_by_phandle(phandle ph) diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index d43fc65749c1..ccf56ac92de5 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -224,7 +224,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, * G5 machines... So when something asks for bus 0 io base * (bus 0 is HT root), we return the AGP one instead. */ - if (in_bus == 0 && of_machine_is_compatible("MacRISC4")) { + if (in_bus == 0 && machine_is_compatible("MacRISC4")) { struct device_node *agp; agp = of_find_compatible_node(NULL, NULL, "u3-agp"); diff --git a/trunk/arch/powerpc/kernel/prom.c b/trunk/arch/powerpc/kernel/prom.c index 43238b2054b6..4ec300862466 100644 --- a/trunk/arch/powerpc/kernel/prom.c +++ b/trunk/arch/powerpc/kernel/prom.c @@ -61,12 +61,365 @@ #define DBG(fmt...) #endif + +static int __initdata dt_root_addr_cells; +static int __initdata dt_root_size_cells; + #ifdef CONFIG_PPC64 int __initdata iommu_is_off; int __initdata iommu_force_on; unsigned long tce_alloc_start, tce_alloc_end; #endif +typedef u32 cell_t; + +#if 0 +static struct boot_param_header *initial_boot_params __initdata; +#else +struct boot_param_header *initial_boot_params; +#endif + +extern struct device_node *allnodes; /* temporary while merging */ + +extern rwlock_t devtree_lock; /* temporary while merging */ + +/* export that to outside world */ +struct device_node *of_chosen; + +static inline char *find_flat_dt_string(u32 offset) +{ + return ((char *)initial_boot_params) + + initial_boot_params->off_dt_strings + offset; +} + +/** + * This function is used to scan the flattened device-tree, it is + * used to extract the memory informations at boot before we can + * unflatten the tree + */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + int rc = 0; + int depth = -1; + + do { + u32 tag = *((u32 *)p); + char *pathp; + + p += 4; + if (tag == OF_DT_END_NODE) { + depth --; + continue; + } + if (tag == OF_DT_NOP) + continue; + if (tag == OF_DT_END) + break; + if (tag == OF_DT_PROP) { + u32 sz = *((u32 *)p); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + p += sz; + p = _ALIGN(p, 4); + continue; + } + if (tag != OF_DT_BEGIN_NODE) { + printk(KERN_WARNING "Invalid tag %x scanning flattened" + " device tree !\n", tag); + return -EINVAL; + } + depth++; + pathp = (char *)p; + p = _ALIGN(p + strlen(pathp) + 1, 4); + if ((*pathp) == '/') { + char *lp, *np; + for (lp = NULL, np = pathp; *np; np++) + if ((*np) == '/') + lp = np+1; + if (lp != NULL) + pathp = lp; + } + rc = it(p, pathp, depth, data); + if (rc != 0) + break; + } while(1); + + return rc; +} + +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while(*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + +/** + * This function can be used within scan_flattened_dt callback to get + * access to properties + */ +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) +{ + unsigned long p = node; + + do { + u32 tag = *((u32 *)p); + u32 sz, noff; + const char *nstr; + + p += 4; + if (tag == OF_DT_NOP) + continue; + if (tag != OF_DT_PROP) + return NULL; + + sz = *((u32 *)p); + noff = *((u32 *)(p + 4)); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + + nstr = find_flat_dt_string(noff); + if (nstr == NULL) { + printk(KERN_WARNING "Can't find property index" + " name !\n"); + return NULL; + } + if (strcmp(name, nstr) == 0) { + if (size) + *size = sz; + return (void *)p; + } + p += sz; + p = _ALIGN(p, 4); + } while(1); +} + +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char* cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + +static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, + unsigned long align) +{ + void *res; + + *mem = _ALIGN(*mem, align); + res = (void *)*mem; + *mem += size; + + return res; +} + +static unsigned long __init unflatten_dt_node(unsigned long mem, + unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp, + unsigned long fpsize) +{ + struct device_node *np; + struct property *pp, **prev_pp = NULL; + char *pathp; + u32 tag; + unsigned int l, allocl; + int has_name = 0; + int new_format = 0; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_BEGIN_NODE) { + printk("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + pathp = (char *)*p; + l = allocl = strlen(pathp) + 1; + *p = _ALIGN(*p + l, 4); + + /* version 0x10 has a more compact unit name here instead of the full + * path. we accumulate the full path size using "fpsize", we'll rebuild + * it later. We detect this because the first character of the name is + * not '/'. + */ + if ((*pathp) != '/') { + new_format = 1; + if (fpsize == 0) { + /* root node: special case. fpsize accounts for path + * plus terminating zero. root node only has '/', so + * fpsize should be 2, but we want to avoid the first + * level nodes to have two '/' so we use fpsize 1 here + */ + fpsize = 1; + allocl = 2; + } else { + /* account for '/' and path size minus terminal 0 + * already in 'l' + */ + fpsize += l; + allocl = fpsize; + } + } + + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, + __alignof__(struct device_node)); + if (allnextpp) { + memset(np, 0, sizeof(*np)); + np->full_name = ((char*)np) + sizeof(struct device_node); + if (new_format) { + char *p = np->full_name; + /* rebuild full path for new format */ + if (dad && dad->parent) { + strcpy(p, dad->full_name); +#ifdef DEBUG + if ((strlen(p) + l + 1) != allocl) { + DBG("%s: p: %d, l: %d, a: %d\n", + pathp, (int)strlen(p), l, allocl); + } +#endif + p += strlen(p); + } + *(p++) = '/'; + memcpy(p, pathp, l); + } else + memcpy(np->full_name, pathp, l); + prev_pp = &np->properties; + **allnextpp = np; + *allnextpp = &np->allnext; + if (dad != NULL) { + np->parent = dad; + /* we temporarily use the next field as `last_child'*/ + if (dad->next == 0) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + kref_init(&np->kref); + } + while(1) { + u32 sz, noff; + char *pname; + + tag = *((u32 *)(*p)); + if (tag == OF_DT_NOP) { + *p += 4; + continue; + } + if (tag != OF_DT_PROP) + break; + *p += 4; + sz = *((u32 *)(*p)); + noff = *((u32 *)((*p) + 4)); + *p += 8; + if (initial_boot_params->version < 0x10) + *p = _ALIGN(*p, sz >= 8 ? 8 : 4); + + pname = find_flat_dt_string(noff); + if (pname == NULL) { + printk("Can't find property name in list !\n"); + break; + } + if (strcmp(pname, "name") == 0) + has_name = 1; + l = strlen(pname) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property), + __alignof__(struct property)); + if (allnextpp) { + if (strcmp(pname, "linux,phandle") == 0) { + np->node = *((u32 *)*p); + if (np->linux_phandle == 0) + np->linux_phandle = np->node; + } + if (strcmp(pname, "ibm,phandle") == 0) + np->linux_phandle = *((u32 *)*p); + pp->name = pname; + pp->length = sz; + pp->value = (void *)*p; + *prev_pp = pp; + prev_pp = &pp->next; + } + *p = _ALIGN((*p) + sz, 4); + } + /* with version 0x10 we may not have the name property, recreate + * it here from the unit name if absent + */ + if (!has_name) { + char *p = pathp, *ps = pathp, *pa = NULL; + int sz; + + while (*p) { + if ((*p) == '@') + pa = p; + if ((*p) == '/') + ps = p + 1; + p++; + } + if (pa < ps) + pa = p; + sz = (pa - ps) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, + __alignof__(struct property)); + if (allnextpp) { + pp->name = "name"; + pp->length = sz; + pp->value = pp + 1; + *prev_pp = pp; + prev_pp = &pp->next; + memcpy(pp->value, ps, sz - 1); + ((char *)pp->value)[sz - 1] = 0; + DBG("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); + } + } + if (allnextpp) { + *prev_pp = NULL; + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); + + if (!np->name) + np->name = ""; + if (!np->type) + np->type = ""; + } + while (tag == OF_DT_BEGIN_NODE) { + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); + tag = *((u32 *)(*p)); + } + if (tag != OF_DT_END_NODE) { + printk("Weird tag at end of node: %x\n", tag); + return mem; + } + *p += 4; + return mem; +} + static int __init early_parse_mem(char *p) { if (!p) @@ -93,7 +446,7 @@ static void __init move_device_tree(void) DBG("-> move_device_tree\n"); start = __pa(initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); + size = initial_boot_params->totalsize; if ((memory_limit && (start + size) > memory_limit) || overlaps_crashkernel(start, size)) { @@ -106,6 +459,54 @@ static void __init move_device_tree(void) DBG("<- move_device_tree\n"); } +/** + * unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used (this used to be done by finish_device_tree) + */ +void __init unflatten_device_tree(void) +{ + unsigned long start, mem, size; + struct device_node **allnextp = &allnodes; + + DBG(" -> unflatten_device_tree()\n"); + + /* First pass, scan for size */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + size = unflatten_dt_node(0, &start, NULL, NULL, 0); + size = (size | 3) + 1; + + DBG(" size is %lx, allocating...\n", size); + + /* Allocate memory for the expanded device tree */ + mem = lmb_alloc(size + 4, __alignof__(struct device_node)); + mem = (unsigned long) __va(mem); + + ((u32 *)mem)[size / 4] = 0xdeadbeef; + + DBG(" unflattening %lx...\n", mem); + + /* Second pass, do actual unflattening */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + unflatten_dt_node(mem, &start, NULL, &allnextp, 0); + if (*((u32 *)start) != OF_DT_END) + printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); + if (((u32 *)mem)[size / 4] != 0xdeadbeef) + printk(KERN_WARNING "End of tree marker overwritten: %08x\n", + ((u32 *)mem)[size / 4] ); + *allnextp = NULL; + + /* Get pointer to OF "/chosen" node for use everywhere */ + of_chosen = of_find_node_by_path("/chosen"); + if (of_chosen == NULL) + of_chosen = of_find_node_by_path("/chosen@0"); + + DBG(" <- unflatten_device_tree()\n"); +} + /* * ibm,pa-features is a per-cpu property that contains a string of * attribute descriptors, each of which has a 2 byte header plus up @@ -362,9 +763,48 @@ static int __init early_init_dt_scan_cpus(unsigned long node, return 0; } -void __init early_init_dt_scan_chosen_arch(unsigned long node) +#ifdef CONFIG_BLK_DEV_INITRD +static void __init early_init_dt_check_for_initrd(unsigned long node) +{ + unsigned long l; + u32 *prop; + + DBG("Looking for initrd properties... "); + + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); + + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long) + __va(of_read_ulong(prop, l/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + + DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); +} +#else +static inline void early_init_dt_check_for_initrd(unsigned long node) +{ +} +#endif /* CONFIG_BLK_DEV_INITRD */ + +static int __init early_init_dt_scan_chosen(unsigned long node, + const char *uname, int depth, void *data) { unsigned long *lprop; + unsigned long l; + char *p; + + DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + + if (depth != 1 || + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ @@ -375,17 +815,17 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node) #endif /* mem=x on the command line is the preferred mechanism */ - lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); - if (lprop) - memory_limit = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); + if (lprop) + memory_limit = *lprop; #ifdef CONFIG_PPC64 - lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); - if (lprop) - tce_alloc_start = *lprop; - lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); - if (lprop) - tce_alloc_end = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + if (lprop) + tce_alloc_start = *lprop; + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + if (lprop) + tce_alloc_end = *lprop; #endif #ifdef CONFIG_KEXEC @@ -397,6 +837,51 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node) if (lprop) crashk_res.end = crashk_res.start + *lprop - 1; #endif + + early_init_dt_check_for_initrd(node); + + /* Retreive command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); + +#ifdef CONFIG_CMDLINE + if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif /* CONFIG_CMDLINE */ + + DBG("Command line is: %s\n", cmd_line); + + /* break now */ + return 1; +} + +static int __init early_init_dt_scan_root(unsigned long node, + const char *uname, int depth, void *data) +{ + u32 *prop; + + if (depth != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + dt_root_size_cells = (prop == NULL) ? 1 : *prop; + DBG("dt_root_size_cells = %x\n", dt_root_size_cells); + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); + + /* break now */ + return 1; +} + +static u64 __init dt_mem_next_cell(int s, cell_t **cellp) +{ + cell_t *p = *cellp; + + *cellp = p + s; + return of_read_number(p, s); } #ifdef CONFIG_PPC_PSERIES @@ -408,22 +893,22 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node) */ static int __init early_init_dt_scan_drconf_memory(unsigned long node) { - __be32 *dm, *ls, *usm; + cell_t *dm, *ls, *usm; unsigned long l, n, flags; u64 base, size, lmb_size; unsigned int is_kexec_kdump = 0, rngs; ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); - if (ls == NULL || l < dt_root_size_cells * sizeof(__be32)) + if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) return 0; lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); - if (dm == NULL || l < sizeof(__be32)) + if (dm == NULL || l < sizeof(cell_t)) return 0; n = *dm++; /* number of entries */ - if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(__be32)) + if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) return 0; /* check if this is a kexec/kdump kernel. */ @@ -478,47 +963,65 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) #define early_init_dt_scan_drconf_memory(node) 0 #endif /* CONFIG_PPC_PSERIES */ -static int __init early_init_dt_scan_memory_ppc(unsigned long node, - const char *uname, - int depth, void *data) +static int __init early_init_dt_scan_memory(unsigned long node, + const char *uname, int depth, void *data) { + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + cell_t *reg, *endp; + unsigned long l; + + /* Look for the ibm,dynamic-reconfiguration-memory node */ if (depth == 1 && strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) return early_init_dt_scan_drconf_memory(node); - - return early_init_dt_scan_memory(node, uname, depth, data); -} -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ -#if defined(CONFIG_PPC64) - if (iommu_is_off) { - if (base >= 0x80000000ul) - return; - if ((base + size) > 0x80000000ul) - size = 0x80000000ul - base; - } -#endif + /* We are scanning "memory" nodes only */ + if (type == NULL) { + /* + * The longtrail doesn't have a device_type on the + * /memory node, so look for the node called /memory@0. + */ + if (depth != 1 || strcmp(uname, "memory@0") != 0) + return 0; + } else if (strcmp(type, "memory") != 0) + return 0; - lmb_add(base, size); + reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); + if (reg == NULL) + reg = of_get_flat_dt_prop(node, "reg", &l); + if (reg == NULL) + return 0; - memstart_addr = min((u64)memstart_addr, base); -} + endp = reg + (l / sizeof(cell_t)); -u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) -{ - return lmb_alloc(size, align); -} + DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", + uname, l, reg[0], reg[1], reg[2], reg[3]); -#ifdef CONFIG_BLK_DEV_INITRD -void __init early_init_dt_setup_initrd_arch(unsigned long start, - unsigned long end) -{ - initrd_start = (unsigned long)__va(start); - initrd_end = (unsigned long)__va(end); - initrd_below_start_ok = 1; -} + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + u64 base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + + if (size == 0) + continue; + DBG(" - %llx , %llx\n", (unsigned long long)base, + (unsigned long long)size); +#ifdef CONFIG_PPC64 + if (iommu_is_off) { + if (base >= 0x80000000ul) + continue; + if ((base + size) > 0x80000000ul) + size = 0x80000000ul - base; + } #endif + lmb_add(base, size); + + memstart_addr = min((u64)memstart_addr, base); + } + + return 0; +} static void __init early_reserve_mem(void) { @@ -683,7 +1186,7 @@ void __init early_init_devtree(void *params) /* Scan memory nodes and rebuild LMBs */ lmb_init(); of_scan_flat_dt(early_init_dt_scan_root, NULL); - of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); /* Save command line for /proc/cmdline and then parse parameters */ strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); @@ -731,6 +1234,25 @@ void __init early_init_devtree(void *params) DBG(" <- early_init_devtree()\n"); } + +/** + * Indicates whether the root node has a given value in its + * compatible property. + */ +int machine_is_compatible(const char *compat) +{ + struct device_node *root; + int rc = 0; + + root = of_find_node_by_path("/"); + if (root) { + rc = of_device_is_compatible(root, compat); + of_node_put(root); + } + return rc; +} +EXPORT_SYMBOL(machine_is_compatible); + /******* * * New implementation of the OF "find" APIs, return a refcounted @@ -742,6 +1264,27 @@ void __init early_init_devtree(void *params) * *******/ +/** + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + read_lock(&devtree_lock); + for (np = allnodes; np != 0; np = np->allnext) + if (np->linux_phandle == handle) + break; + of_node_get(np); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + /** * of_find_next_cache_node - Find a node's subsidiary cache * @np: node of type "cpu" or "cache" @@ -773,6 +1316,138 @@ struct device_node *of_find_next_cache_node(struct device_node *np) return NULL; } +/** + * of_node_get - Increment refcount of a node + * @node: Node to inc refcount, NULL is supported to + * simplify writing of callers + * + * Returns node. + */ +struct device_node *of_node_get(struct device_node *node) +{ + if (node) + kref_get(&node->kref); + return node; +} +EXPORT_SYMBOL(of_node_get); + +static inline struct device_node * kref_to_device_node(struct kref *kref) +{ + return container_of(kref, struct device_node, kref); +} + +/** + * of_node_release - release a dynamically allocated node + * @kref: kref element of the node to be released + * + * In of_node_put() this function is passed to kref_put() + * as the destructor. + */ +static void of_node_release(struct kref *kref) +{ + struct device_node *node = kref_to_device_node(kref); + struct property *prop = node->properties; + + /* We should never be releasing nodes that haven't been detached. */ + if (!of_node_check_flag(node, OF_DETACHED)) { + printk("WARNING: Bad of_node_put() on %s\n", node->full_name); + dump_stack(); + kref_init(&node->kref); + return; + } + + if (!of_node_check_flag(node, OF_DYNAMIC)) + return; + + while (prop) { + struct property *next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + prop = next; + + if (!prop) { + prop = node->deadprops; + node->deadprops = NULL; + } + } + kfree(node->full_name); + kfree(node->data); + kfree(node); +} + +/** + * of_node_put - Decrement refcount of a node + * @node: Node to dec refcount, NULL is supported to + * simplify writing of callers + * + */ +void of_node_put(struct device_node *node) +{ + if (node) + kref_put(&node->kref, of_node_release); +} +EXPORT_SYMBOL(of_node_put); + +/* + * Plug a device node into the tree and global list. + */ +void of_attach_node(struct device_node *np) +{ + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + np->sibling = np->parent->child; + np->allnext = allnodes; + np->parent->child = np; + allnodes = np; + write_unlock_irqrestore(&devtree_lock, flags); +} + +/* + * "Unplug" a node from the device tree. The caller must hold + * a reference to the node. The memory associated with the node + * is not freed until its refcount goes to zero. + */ +void of_detach_node(struct device_node *np) +{ + struct device_node *parent; + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + + parent = np->parent; + if (!parent) + goto out_unlock; + + if (allnodes == np) + allnodes = np->allnext; + else { + struct device_node *prev; + for (prev = allnodes; + prev->allnext != np; + prev = prev->allnext) + ; + prev->allnext = np->allnext; + } + + if (parent->child == np) + parent->child = np->sibling; + else { + struct device_node *prevsib; + for (prevsib = np->parent->child; + prevsib->sibling != np; + prevsib = prevsib->sibling) + ; + prevsib->sibling = np->sibling; + } + + of_node_set_flag(np, OF_DETACHED); + +out_unlock: + write_unlock_irqrestore(&devtree_lock, flags); +} + #ifdef CONFIG_PPC_PSERIES /* * Fix up the uninitialized fields in a new device node: @@ -804,9 +1479,9 @@ static int of_finish_dynamic_node(struct device_node *node) if (machine_is(powermac)) return -ENODEV; - /* fix up new node's phandle field */ + /* fix up new node's linux_phandle field */ if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) - node->phandle = *ibm_phandle; + node->linux_phandle = *ibm_phandle; out: of_node_put(parent); @@ -845,6 +1520,120 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif +/* + * Add a property to a node + */ +int prom_add_property(struct device_node* np, struct property* prop) +{ + struct property **next; + unsigned long flags; + + prop->next = NULL; + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock_irqrestore(&devtree_lock, flags); + return -1; + } + next = &(*next)->next; + } + *next = prop; + write_unlock_irqrestore(&devtree_lock, flags); + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Remove a property from a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, so it won't be found any more. + */ +int prom_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == prop) { + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to remove the proc node as well */ + if (np->pde) + proc_device_tree_remove_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Update a property in a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, and add the new property to the + * property list + */ +int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_update_prop(np->pde, newprop, oldprop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + + /* Find the device node for a given logical cpu number, also returns the cpu * local thread number (index in ibm,interrupt-server#s) if relevant and * asked for (non NULL) diff --git a/trunk/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/trunk/arch/powerpc/platforms/85xx/xes_mpc85xx.c index 0125604d096e..1b426050a2f9 100644 --- a/trunk/arch/powerpc/platforms/85xx/xes_mpc85xx.c +++ b/trunk/arch/powerpc/platforms/85xx/xes_mpc85xx.c @@ -80,8 +80,8 @@ static void xes_mpc85xx_configure_l2(void __iomem *l2_base) printk(KERN_INFO "xes_mpc85xx: Enabling L2 as cache\n"); ctl = MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2I; - if (of_machine_is_compatible("MPC8540") || - of_machine_is_compatible("MPC8560")) + if (machine_is_compatible("MPC8540") || + machine_is_compatible("MPC8560")) /* * Assume L2 SRAM is used fully for cache, so set * L2BLKSZ (bits 4:5) to match L2SIZ (bits 2:3). diff --git a/trunk/arch/powerpc/platforms/cell/cbe_powerbutton.c b/trunk/arch/powerpc/platforms/cell/cbe_powerbutton.c index f75a4daa4ca2..dcddaa5fcb66 100644 --- a/trunk/arch/powerpc/platforms/cell/cbe_powerbutton.c +++ b/trunk/arch/powerpc/platforms/cell/cbe_powerbutton.c @@ -48,7 +48,7 @@ static int __init cbe_powerbutton_init(void) int ret = 0; struct input_dev *dev; - if (!of_machine_is_compatible("IBM,CBPLUS-1.0")) { + if (!machine_is_compatible("IBM,CBPLUS-1.0")) { printk(KERN_ERR "%s: Not a cell blade.\n", __func__); ret = -ENODEV; goto out; diff --git a/trunk/arch/powerpc/platforms/cell/ras.c b/trunk/arch/powerpc/platforms/cell/ras.c index 608fd2b584c9..5e0a191764fc 100644 --- a/trunk/arch/powerpc/platforms/cell/ras.c +++ b/trunk/arch/powerpc/platforms/cell/ras.c @@ -255,7 +255,7 @@ static int __init cbe_sysreset_init(void) { struct cbe_pmd_regs __iomem *regs; - sysreset_hack = of_machine_is_compatible("IBM,CBPLUS-1.0"); + sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0"); if (!sysreset_hack) return 0; diff --git a/trunk/arch/powerpc/platforms/cell/spu_manage.c b/trunk/arch/powerpc/platforms/cell/spu_manage.c index 891f18e337a2..4c506c1463cd 100644 --- a/trunk/arch/powerpc/platforms/cell/spu_manage.c +++ b/trunk/arch/powerpc/platforms/cell/spu_manage.c @@ -457,7 +457,7 @@ neighbour_spu(int cbe, struct device_node *target, struct device_node *avoid) continue; vic_handles = of_get_property(spu_dn, "vicinity", &lenp); for (i=0; i < (lenp / sizeof(phandle)); i++) { - if (vic_handles[i] == target->phandle) + if (vic_handles[i] == target->linux_phandle) return spu; } } @@ -499,7 +499,7 @@ static void init_affinity_node(int cbe) if (strcmp(name, "spe") == 0) { spu = devnode_spu(cbe, vic_dn); - avoid_ph = last_spu_dn->phandle; + avoid_ph = last_spu_dn->linux_phandle; } else { /* * "mic-tm" and "bif0" nodes do not have @@ -514,7 +514,7 @@ static void init_affinity_node(int cbe) last_spu->has_mem_affinity = 1; spu->has_mem_affinity = 1; } - avoid_ph = vic_dn->phandle; + avoid_ph = vic_dn->linux_phandle; } list_add_tail(&spu->aff_list, &last_spu->aff_list); diff --git a/trunk/arch/powerpc/platforms/pasemi/cpufreq.c b/trunk/arch/powerpc/platforms/pasemi/cpufreq.c index d35e0520abf0..be2527a516ea 100644 --- a/trunk/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/trunk/arch/powerpc/platforms/pasemi/cpufreq.c @@ -304,8 +304,8 @@ static struct cpufreq_driver pas_cpufreq_driver = { static int __init pas_cpufreq_init(void) { - if (!of_machine_is_compatible("PA6T-1682M") && - !of_machine_is_compatible("pasemi,pwrficient")) + if (!machine_is_compatible("PA6T-1682M") && + !machine_is_compatible("pasemi,pwrficient")) return -ENODEV; return cpufreq_register_driver(&pas_cpufreq_driver); diff --git a/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c b/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c index d4f127d18141..08d94e4cedd3 100644 --- a/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/trunk/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -657,31 +657,31 @@ static int __init pmac_cpufreq_setup(void) cur_freq = (*value) / 1000; /* Check for 7447A based MacRISC3 */ - if (of_machine_is_compatible("MacRISC3") && + if (machine_is_compatible("MacRISC3") && of_get_property(cpunode, "dynamic-power-step", NULL) && PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { pmac_cpufreq_init_7447A(cpunode); /* Check for other MacRISC3 machines */ - } else if (of_machine_is_compatible("PowerBook3,4") || - of_machine_is_compatible("PowerBook3,5") || - of_machine_is_compatible("MacRISC3")) { + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { pmac_cpufreq_init_MacRISC3(cpunode); /* Else check for iBook2 500/600 */ - } else if (of_machine_is_compatible("PowerBook4,1")) { + } else if (machine_is_compatible("PowerBook4,1")) { hi_freq = cur_freq; low_freq = 400000; set_speed_proc = pmu_set_cpu_speed; is_pmu_based = 1; } /* Else check for TiPb 550 */ - else if (of_machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { + else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { hi_freq = cur_freq; low_freq = 500000; set_speed_proc = pmu_set_cpu_speed; is_pmu_based = 1; } /* Else check for TiPb 400 & 500 */ - else if (of_machine_is_compatible("PowerBook3,2")) { + else if (machine_is_compatible("PowerBook3,2")) { /* We only know about the 400 MHz and the 500Mhz model * they both have 300 MHz as low frequency */ diff --git a/trunk/arch/powerpc/platforms/powermac/cpufreq_64.c b/trunk/arch/powerpc/platforms/powermac/cpufreq_64.c index 3ed288e68ec4..708c75133377 100644 --- a/trunk/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/trunk/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -398,11 +398,11 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) int rc = -ENODEV; /* Check supported platforms */ - if (of_machine_is_compatible("PowerMac8,1") || - of_machine_is_compatible("PowerMac8,2") || - of_machine_is_compatible("PowerMac9,1")) + if (machine_is_compatible("PowerMac8,1") || + machine_is_compatible("PowerMac8,2") || + machine_is_compatible("PowerMac9,1")) use_volts_smu = 1; - else if (of_machine_is_compatible("PowerMac11,2")) + else if (machine_is_compatible("PowerMac11,2")) use_volts_vdnap = 1; else return -ENODEV; @@ -729,9 +729,9 @@ static int __init g5_cpufreq_init(void) return -ENODEV; } - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) rc = g5_pm72_cpufreq_init(cpus); #ifdef CONFIG_PMAC_SMU else diff --git a/trunk/arch/powerpc/platforms/powermac/feature.c b/trunk/arch/powerpc/platforms/powermac/feature.c index 33e815f4466c..fbc9bbd74dbd 100644 --- a/trunk/arch/powerpc/platforms/powermac/feature.c +++ b/trunk/arch/powerpc/platforms/powermac/feature.c @@ -2426,7 +2426,7 @@ static int __init probe_motherboard(void) } } for(i=0; ifunctions, link) { if (name && strcmp(name, func->name)) continue; - if (func->phandle && target->phandle != func->phandle) + if (func->phandle && target->node != func->phandle) continue; if ((func->flags & flags) == 0) continue; diff --git a/trunk/arch/powerpc/platforms/powermac/smp.c b/trunk/arch/powerpc/platforms/powermac/smp.c index 6898e8241cd0..b40c22d697f0 100644 --- a/trunk/arch/powerpc/platforms/powermac/smp.c +++ b/trunk/arch/powerpc/platforms/powermac/smp.c @@ -693,9 +693,9 @@ static void __init smp_core99_setup(int ncpus) #ifdef CONFIG_PPC64 /* i2c based HW sync on some G5s */ - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) smp_core99_setup_i2c_hwsync(ncpus); /* pfunc based HW sync on recent G5s */ @@ -713,7 +713,7 @@ static void __init smp_core99_setup(int ncpus) #else /* CONFIG_PPC64 */ /* GPIO based HW sync on ppc32 Core99 */ - if (pmac_tb_freeze == NULL && !of_machine_is_compatible("MacRISC4")) { + if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) { struct device_node *cpu; const u32 *tbprop = NULL; @@ -750,7 +750,7 @@ static void __init smp_core99_setup(int ncpus) #endif /* 32 bits SMP can't NAP */ - if (!of_machine_is_compatible("MacRISC4")) + if (!machine_is_compatible("MacRISC4")) powersave_nap = 0; } @@ -852,7 +852,7 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr) /* If we didn't start the second CPU, we must take * it off the bus */ - if (of_machine_is_compatible("MacRISC4") && + if (machine_is_compatible("MacRISC4") && num_online_cpus() < 2) g5_phy_disable_cpu1(); #endif /* CONFIG_PPC64 */ diff --git a/trunk/arch/powerpc/platforms/powermac/time.c b/trunk/arch/powerpc/platforms/powermac/time.c index 48211ca134c3..1810e4226e56 100644 --- a/trunk/arch/powerpc/platforms/powermac/time.c +++ b/trunk/arch/powerpc/platforms/powermac/time.c @@ -317,9 +317,9 @@ void __init pmac_calibrate_decr(void) * calibration. That's better since the VIA itself seems * to be slightly off. --BenH */ - if (!of_machine_is_compatible("MacRISC2") && - !of_machine_is_compatible("MacRISC3") && - !of_machine_is_compatible("MacRISC4")) + if (!machine_is_compatible("MacRISC2") && + !machine_is_compatible("MacRISC3") && + !machine_is_compatible("MacRISC4")) if (via_calibrate_decr()) return; @@ -328,7 +328,7 @@ void __init pmac_calibrate_decr(void) * probably implement calibration based on the KL timer on these * machines anyway... -BenH */ - if (of_machine_is_compatible("PowerMac3,5")) + if (machine_is_compatible("PowerMac3,5")) if (via_calibrate_decr()) return; #endif diff --git a/trunk/arch/powerpc/platforms/powermac/udbg_scc.c b/trunk/arch/powerpc/platforms/powermac/udbg_scc.c index d83135a9830e..9490157da62e 100644 --- a/trunk/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/trunk/arch/powerpc/platforms/powermac/udbg_scc.c @@ -132,9 +132,9 @@ void udbg_scc_init(int force_scc) scc_inittab[1] = in_8(sccc); out_8(sccc, 12); scc_inittab[3] = in_8(sccc); - } else if (of_machine_is_compatible("RackMac1,1") - || of_machine_is_compatible("RackMac1,2") - || of_machine_is_compatible("MacRISC4")) { + } else if (machine_is_compatible("RackMac1,1") + || machine_is_compatible("RackMac1,2") + || machine_is_compatible("MacRISC4")) { /* Xserves and G5s default to 57600 */ scc_inittab[1] = 0; scc_inittab[3] = 0; diff --git a/trunk/arch/powerpc/sysdev/grackle.c b/trunk/arch/powerpc/sysdev/grackle.c index cf27df6e508b..5da37c2f22ee 100644 --- a/trunk/arch/powerpc/sysdev/grackle.c +++ b/trunk/arch/powerpc/sysdev/grackle.c @@ -56,9 +56,9 @@ static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) void __init setup_grackle(struct pci_controller *hose) { setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0); - if (of_machine_is_compatible("PowerMac1,1")) + if (machine_is_compatible("PowerMac1,1")) ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS); - if (of_machine_is_compatible("AAPL,PowerBook1998")) + if (machine_is_compatible("AAPL,PowerBook1998")) grackle_set_loop_snoop(hose, 1); #if 0 /* Disabled for now, HW problems ??? */ grackle_set_stg(hose, 1); diff --git a/trunk/arch/sparc/kernel/devices.c b/trunk/arch/sparc/kernel/devices.c index b062de9424a4..b171ae8de90d 100644 --- a/trunk/arch/sparc/kernel/devices.c +++ b/trunk/arch/sparc/kernel/devices.c @@ -59,7 +59,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, cur_inst = 0; for_each_node_by_type(dp, "cpu") { - int err = check_cpu_node(dp->phandle, &cur_inst, + int err = check_cpu_node(dp->node, &cur_inst, compare, compare_arg, prom_node, mid); if (!err) { diff --git a/trunk/arch/sparc/kernel/of_device_32.c b/trunk/arch/sparc/kernel/of_device_32.c index da527b33ebc7..53a58b349849 100644 --- a/trunk/arch/sparc/kernel/of_device_32.c +++ b/trunk/arch/sparc/kernel/of_device_32.c @@ -433,7 +433,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->phandle); + dev_set_name(&op->dev, "%08x", dp->node); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/trunk/arch/sparc/kernel/of_device_64.c b/trunk/arch/sparc/kernel/of_device_64.c index b3d4cb5d21b3..0a6f2d1798d1 100644 --- a/trunk/arch/sparc/kernel/of_device_64.c +++ b/trunk/arch/sparc/kernel/of_device_64.c @@ -676,7 +676,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, if (!parent) dev_set_name(&op->dev, "root"); else - dev_set_name(&op->dev, "%08x", dp->phandle); + dev_set_name(&op->dev, "%08x", dp->node); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/trunk/arch/sparc/kernel/prom.h b/trunk/arch/sparc/kernel/prom.h index a8591ef2636d..453397fe5e14 100644 --- a/trunk/arch/sparc/kernel/prom.h +++ b/trunk/arch/sparc/kernel/prom.h @@ -4,6 +4,9 @@ #include #include +extern struct device_node *allnodes; /* temporary while merging */ +extern rwlock_t devtree_lock; /* temporary while merging */ + extern void * prom_early_alloc(unsigned long size); extern void irq_trans_init(struct device_node *dp); diff --git a/trunk/arch/sparc/kernel/prom_common.c b/trunk/arch/sparc/kernel/prom_common.c index 57ac9e28be0c..d80a65d9e893 100644 --- a/trunk/arch/sparc/kernel/prom_common.c +++ b/trunk/arch/sparc/kernel/prom_common.c @@ -37,6 +37,18 @@ EXPORT_SYMBOL(of_console_path); char *of_console_options; EXPORT_SYMBOL(of_console_options); +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -77,7 +89,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; - ret = prom_setprop(dp->phandle, name, val, len); + ret = prom_setprop(dp->node, name, val, len); err = -EINVAL; if (ret >= 0) { @@ -224,7 +236,7 @@ static struct device_node * __init prom_create_node(phandle node, dp->name = get_one_property(node, "name"); dp->type = get_one_property(node, "device_type"); - dp->phandle = node; + dp->node = node; dp->properties = build_prop_list(node); @@ -301,7 +313,7 @@ void __init prom_build_devicetree(void) nextp = &allnodes->allnext; allnodes->child = prom_build_tree(allnodes, - prom_getchild(allnodes->phandle), + prom_getchild(allnodes->node), &nextp); of_console_init(); diff --git a/trunk/arch/sparc/kernel/smp_64.c b/trunk/arch/sparc/kernel/smp_64.c index eb14844a0021..aa36223497b9 100644 --- a/trunk/arch/sparc/kernel/smp_64.c +++ b/trunk/arch/sparc/kernel/smp_64.c @@ -370,7 +370,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu) } else { struct device_node *dp = of_find_node_by_cpuid(cpu); - prom_startcpu(dp->phandle, entry, cookie); + prom_startcpu(dp->node, entry, cookie); } for (timeout = 0; timeout < 50000; timeout++) { diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index d1a9a0a64f95..718897e6d37f 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -1147,7 +1147,7 @@ void init_request_from_bio(struct request *req, struct bio *bio) */ static inline bool queue_should_plug(struct request_queue *q) { - return !(blk_queue_nonrot(q) && blk_queue_tagged(q)); + return !(blk_queue_nonrot(q) && blk_queue_queuing(q)); } static int __make_request(struct request_queue *q, struct bio *bio) @@ -1859,8 +1859,15 @@ void blk_dequeue_request(struct request *rq) * and to it is freed is accounted as io that is in progress at * the driver side. */ - if (blk_account_rq(rq)) + if (blk_account_rq(rq)) { q->in_flight[rq_is_sync(rq)]++; + /* + * Mark this device as supporting hardware queuing, if + * we have more IOs in flight than 4. + */ + if (!blk_queue_queuing(q) && queue_in_flight(q) > 4) + set_bit(QUEUE_FLAG_CQ, &q->queue_flags); + } } /** diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index cc978a8c00b7..e88e8ae04fdb 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -880,14 +880,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, return(acpi_idle_enter_c1(dev, state)); local_irq_disable(); - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - } + current_thread_info()->status &= ~TS_POLLING; + /* + * TS_POLLING-cleared state must be visible before we test + * NEED_RESCHED: + */ + smp_mb(); if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; @@ -967,14 +965,12 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, } local_irq_disable(); - if (cx->entry_method != ACPI_CSTATE_FFH) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - } + current_thread_info()->status &= ~TS_POLLING; + /* + * TS_POLLING-cleared state must be visible before we test + * NEED_RESCHED: + */ + smp_mb(); if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index a959f6a07508..2cabadcc4d8c 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -413,11 +413,7 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) if (result) goto update_bios; - /* We need to call _PPC once when cpufreq starts */ - if (ignore_ppc != 1) - result = acpi_processor_get_platform_limit(pr); - - return result; + return 0; /* * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index a6a736a7dbf2..b34390347c16 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -3082,16 +3082,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ahci_save_initial_config(pdev, hpriv); /* prepare host */ - if (hpriv->cap & HOST_CAP_NCQ) { - pi.flags |= ATA_FLAG_NCQ; - /* Auto-activate optimization is supposed to be supported on - all AHCI controllers indicating NCQ support, but it seems - to be broken at least on some NVIDIA MCP79 chipsets. - Until we get info on which NVIDIA chipsets don't have this - issue, if any, disable AA on all NVIDIA AHCIs. */ - if (pdev->vendor != PCI_VENDOR_ID_NVIDIA) - pi.flags |= ATA_FLAG_FPDMA_AA; - } + if (hpriv->cap & HOST_CAP_NCQ) + pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA; if (hpriv->cap & HOST_CAP_PMP) pi.flags |= ATA_FLAG_PMP; diff --git a/trunk/drivers/block/virtio_blk.c b/trunk/drivers/block/virtio_blk.c index 7eff828b2117..51042f0ba7e1 100644 --- a/trunk/drivers/block/virtio_blk.c +++ b/trunk/drivers/block/virtio_blk.c @@ -243,12 +243,10 @@ static int index_to_minor(int index) static int __devinit virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; - struct request_queue *q; int err; u64 cap; - u32 v, blk_size, sg_elems, opt_io_size; - u16 min_io_size; - u8 physical_block_exp, alignment_offset; + u32 v; + u32 blk_size, sg_elems; if (index_to_minor(index) >= 1 << MINORBITS) return -ENOSPC; @@ -295,13 +293,13 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) goto out_mempool; } - q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); - if (!q) { + vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); + if (!vblk->disk->queue) { err = -ENOMEM; goto out_put_disk; } - q->queuedata = vblk; + vblk->disk->queue->queuedata = vblk; if (index < 26) { sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); @@ -325,10 +323,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) /* If barriers are supported, tell block layer that queue is ordered */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, + blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, virtblk_prepare_flush); else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) - blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); /* If disk is read-only in the host, the guest should obey */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) @@ -347,14 +345,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) set_capacity(vblk->disk, cap); /* We can handle whatever the host told us to handle. */ - blk_queue_max_phys_segments(q, vblk->sg_elems-2); - blk_queue_max_hw_segments(q, vblk->sg_elems-2); + blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); + blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); /* No need to bounce any requests */ - blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); + blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY); /* No real sector limit. */ - blk_queue_max_sectors(q, -1U); + blk_queue_max_sectors(vblk->disk->queue, -1U); /* Host can optionally specify maximum segment size and number of * segments. */ @@ -362,45 +360,16 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) offsetof(struct virtio_blk_config, size_max), &v); if (!err) - blk_queue_max_segment_size(q, v); + blk_queue_max_segment_size(vblk->disk->queue, v); else - blk_queue_max_segment_size(q, -1U); + blk_queue_max_segment_size(vblk->disk->queue, -1U); /* Host can optionally specify the block size of the device */ err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, offsetof(struct virtio_blk_config, blk_size), &blk_size); if (!err) - blk_queue_logical_block_size(q, blk_size); - else - blk_size = queue_logical_block_size(q); - - /* Use topology information if available */ - err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, - offsetof(struct virtio_blk_config, physical_block_exp), - &physical_block_exp); - if (!err && physical_block_exp) - blk_queue_physical_block_size(q, - blk_size * (1 << physical_block_exp)); - - err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, - offsetof(struct virtio_blk_config, alignment_offset), - &alignment_offset); - if (!err && alignment_offset) - blk_queue_alignment_offset(q, blk_size * alignment_offset); - - err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, - offsetof(struct virtio_blk_config, min_io_size), - &min_io_size); - if (!err && min_io_size) - blk_queue_io_min(q, blk_size * min_io_size); - - err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, - offsetof(struct virtio_blk_config, opt_io_size), - &opt_io_size); - if (!err && opt_io_size) - blk_queue_io_opt(q, blk_size * opt_io_size); - + blk_queue_logical_block_size(vblk->disk->queue, blk_size); add_disk(vblk->disk); return 0; @@ -443,7 +412,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, - VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY + VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH }; /* diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 3141dd3b6e53..e023682be2c4 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -666,14 +666,6 @@ config VIRTIO_CONSOLE help Virtio console for use with lguest and other hypervisors. - Also serves as a general-purpose serial device for data - transfer between the guest and host. Character devices at - /dev/vportNpn will be created when corresponding ports are - found, where N is the device number and n is the port number - within that device. If specified by the host, a sysfs - attribute called 'name' will be populated with a name for - the port which can be used by udev scripts to create a - symlink to the device. config HVCS tristate "IBM Hypervisor Virtual Console Server support" diff --git a/trunk/drivers/char/hvc_beat.c b/trunk/drivers/char/hvc_beat.c index 5fe4631e2a61..0afc8b82212e 100644 --- a/trunk/drivers/char/hvc_beat.c +++ b/trunk/drivers/char/hvc_beat.c @@ -84,7 +84,7 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) return cnt; } -static const struct hv_ops hvc_beat_get_put_ops = { +static struct hv_ops hvc_beat_get_put_ops = { .get_chars = hvc_beat_get_chars, .put_chars = hvc_beat_put_chars, }; @@ -99,7 +99,7 @@ static int hvc_beat_config(char *p) static int __init hvc_beat_console_init(void) { - if (hvc_beat_useit && of_machine_is_compatible("Beat")) { + if (hvc_beat_useit && machine_is_compatible("Beat")) { hvc_instantiate(0, 0, &hvc_beat_get_put_ops); } return 0; diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c index d8dac5820f0e..416d3423150d 100644 --- a/trunk/drivers/char/hvc_console.c +++ b/trunk/drivers/char/hvc_console.c @@ -125,7 +125,7 @@ static struct hvc_struct *hvc_get_by_index(int index) * console interfaces but can still be used as a tty device. This has to be * static because kmalloc will not work during early console init. */ -static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; +static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; @@ -247,7 +247,7 @@ static void destroy_hvc_struct(struct kref *kref) * vty adapters do NOT get an hvc_instantiate() callback since they * appear after early console init. */ -int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops) +int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) { struct hvc_struct *hp; @@ -749,8 +749,7 @@ static const struct tty_operations hvc_ops = { }; struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, - const struct hv_ops *ops, - int outbuf_size) + struct hv_ops *ops, int outbuf_size) { struct hvc_struct *hp; int i; diff --git a/trunk/drivers/char/hvc_console.h b/trunk/drivers/char/hvc_console.h index 52ddf4d3716c..10950ca706d8 100644 --- a/trunk/drivers/char/hvc_console.h +++ b/trunk/drivers/char/hvc_console.h @@ -55,7 +55,7 @@ struct hvc_struct { int outbuf_size; int n_outbuf; uint32_t vtermno; - const struct hv_ops *ops; + struct hv_ops *ops; int irq_requested; int data; struct winsize ws; @@ -76,12 +76,11 @@ struct hv_ops { }; /* Register a vterm and a slot index for use as a console (console_init) */ -extern int hvc_instantiate(uint32_t vtermno, int index, - const struct hv_ops *ops); +extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, - const struct hv_ops *ops, int outbuf_size); + struct hv_ops *ops, int outbuf_size); /* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ extern int hvc_remove(struct hvc_struct *hp); diff --git a/trunk/drivers/char/hvc_iseries.c b/trunk/drivers/char/hvc_iseries.c index fd0242676a2a..936d05bf37fa 100644 --- a/trunk/drivers/char/hvc_iseries.c +++ b/trunk/drivers/char/hvc_iseries.c @@ -197,7 +197,7 @@ static int put_chars(uint32_t vtermno, const char *buf, int count) return sent; } -static const struct hv_ops hvc_get_put_ops = { +static struct hv_ops hvc_get_put_ops = { .get_chars = get_chars, .put_chars = put_chars, .notifier_add = notifier_add_irq, diff --git a/trunk/drivers/char/hvc_iucv.c b/trunk/drivers/char/hvc_iucv.c index 21681a81cc35..fe62bd0e17b7 100644 --- a/trunk/drivers/char/hvc_iucv.c +++ b/trunk/drivers/char/hvc_iucv.c @@ -922,7 +922,7 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev) /* HVC operations */ -static const struct hv_ops hvc_iucv_ops = { +static struct hv_ops hvc_iucv_ops = { .get_chars = hvc_iucv_get_chars, .put_chars = hvc_iucv_put_chars, .notifier_add = hvc_iucv_notifier_add, diff --git a/trunk/drivers/char/hvc_rtas.c b/trunk/drivers/char/hvc_rtas.c index 61c4a61558d9..88590d040046 100644 --- a/trunk/drivers/char/hvc_rtas.c +++ b/trunk/drivers/char/hvc_rtas.c @@ -71,7 +71,7 @@ static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) return i; } -static const struct hv_ops hvc_rtas_get_put_ops = { +static struct hv_ops hvc_rtas_get_put_ops = { .get_chars = hvc_rtas_read_console, .put_chars = hvc_rtas_write_console, }; diff --git a/trunk/drivers/char/hvc_udbg.c b/trunk/drivers/char/hvc_udbg.c index b0957e61a7be..bd63ba878a56 100644 --- a/trunk/drivers/char/hvc_udbg.c +++ b/trunk/drivers/char/hvc_udbg.c @@ -58,7 +58,7 @@ static int hvc_udbg_get(uint32_t vtermno, char *buf, int count) return i; } -static const struct hv_ops hvc_udbg_ops = { +static struct hv_ops hvc_udbg_ops = { .get_chars = hvc_udbg_get, .put_chars = hvc_udbg_put, }; diff --git a/trunk/drivers/char/hvc_vio.c b/trunk/drivers/char/hvc_vio.c index 27370e99c66f..10be343d6ae7 100644 --- a/trunk/drivers/char/hvc_vio.c +++ b/trunk/drivers/char/hvc_vio.c @@ -77,7 +77,7 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) return got; } -static const struct hv_ops hvc_get_put_ops = { +static struct hv_ops hvc_get_put_ops = { .get_chars = filtered_get_chars, .put_chars = hvc_put_chars, .notifier_add = notifier_add_irq, diff --git a/trunk/drivers/char/hvc_xen.c b/trunk/drivers/char/hvc_xen.c index 60446f82a3fc..b1a71638c772 100644 --- a/trunk/drivers/char/hvc_xen.c +++ b/trunk/drivers/char/hvc_xen.c @@ -122,7 +122,7 @@ static int read_console(uint32_t vtermno, char *buf, int len) return recv; } -static const struct hv_ops hvc_ops = { +static struct hv_ops hvc_ops = { .get_chars = read_console, .put_chars = write_console, .notifier_add = notifier_add_irq, diff --git a/trunk/drivers/char/virtio_console.c b/trunk/drivers/char/virtio_console.c index 213373b5f17f..a035ae39a359 100644 --- a/trunk/drivers/char/virtio_console.c +++ b/trunk/drivers/char/virtio_console.c @@ -1,6 +1,18 @@ -/* - * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation - * Copyright (C) 2009, 2010 Red Hat, Inc. +/*D:300 + * The Guest console driver + * + * Writing console drivers is one of the few remaining Dark Arts in Linux. + * Fortunately for us, the path of virtual consoles has been well-trodden by + * the PowerPC folks, who wrote "hvc_console.c" to generically support any + * virtual console. We use that infrastructure which only requires us to write + * the basic put_chars and get_chars functions and call the right register + * functions. + :*/ + +/*M:002 The console can be flooded: while the Guest is processing input the + * Host can send more. Buffering in the Host could alleviate this, but it is a + * difficult problem in general. :*/ +/* Copyright (C) 2006, 2007 Rusty Russell, IBM 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 @@ -16,694 +28,142 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include #include -#include #include -#include -#include -#include -#include #include #include -#include -#include #include "hvc_console.h" -/* - * This is a global struct for storing common data for all the devices - * this driver handles. - * - * Mainly, it has a linked list for all the consoles in one place so - * that callbacks from hvc for get_chars(), put_chars() work properly - * across multiple devices and multiple ports per device. - */ -struct ports_driver_data { - /* Used for registering chardevs */ - struct class *class; - - /* Used for exporting per-port information to debugfs */ - struct dentry *debugfs_dir; - - /* Number of devices this driver is handling */ - unsigned int index; - - /* - * This is used to keep track of the number of hvc consoles - * spawned by this driver. This number is given as the first - * argument to hvc_alloc(). To correctly map an initial - * console spawned via hvc_instantiate to the console being - * hooked up via hvc_alloc, we need to pass the same vtermno. - * - * We also just assume the first console being initialised was - * the first one that got used as the initial console. - */ - unsigned int next_vtermno; - - /* All the console devices handled by this driver */ - struct list_head consoles; -}; -static struct ports_driver_data pdrvdata; - -DEFINE_SPINLOCK(pdrvdata_lock); - -/* This struct holds information that's relevant only for console ports */ -struct console { - /* We'll place all consoles in a list in the pdrvdata struct */ - struct list_head list; - - /* The hvc device associated with this console port */ - struct hvc_struct *hvc; - - /* - * This number identifies the number that we used to register - * with hvc in hvc_instantiate() and hvc_alloc(); this is the - * number passed on by the hvc callbacks to us to - * differentiate between the other console ports handled by - * this driver - */ - u32 vtermno; -}; - -struct port_buffer { - char *buf; - - /* size of the buffer in *buf above */ - size_t size; - - /* used length of the buffer */ - size_t len; - /* offset in the buf from which to consume data */ - size_t offset; -}; - -/* - * This is a per-device struct that stores data common to all the - * ports for that device (vdev->priv). - */ -struct ports_device { - /* - * Workqueue handlers where we process deferred work after - * notification - */ - struct work_struct control_work; - struct work_struct config_work; - - struct list_head ports; - - /* To protect the list of ports */ - spinlock_t ports_lock; - - /* To protect the vq operations for the control channel */ - spinlock_t cvq_lock; - - /* The current config space is stored here */ - struct virtio_console_config config; - - /* The virtio device we're associated with */ - struct virtio_device *vdev; - - /* - * A couple of virtqueues for the control channel: one for - * guest->host transfers, one for host->guest transfers - */ - struct virtqueue *c_ivq, *c_ovq; - - /* Array of per-port IO virtqueues */ - struct virtqueue **in_vqs, **out_vqs; - - /* Used for numbering devices for sysfs and debugfs */ - unsigned int drv_index; - - /* Major number for this device. Ports will be created as minors. */ - int chr_major; -}; - -/* This struct holds the per-port data */ -struct port { - /* Next port in the list, head is in the ports_device */ - struct list_head list; - - /* Pointer to the parent virtio_console device */ - struct ports_device *portdev; - - /* The current buffer from which data has to be fed to readers */ - struct port_buffer *inbuf; - - /* - * To protect the operations on the in_vq associated with this - * port. Has to be a spinlock because it can be called from - * interrupt context (get_char()). - */ - spinlock_t inbuf_lock; - - /* The IO vqs for this port */ - struct virtqueue *in_vq, *out_vq; - - /* File in the debugfs directory that exposes this port's information */ - struct dentry *debugfs_file; - - /* - * The entries in this struct will be valid if this port is - * hooked up to an hvc console - */ - struct console cons; - - /* Each port associates with a separate char device */ - struct cdev cdev; - struct device *dev; - - /* A waitqueue for poll() or blocking read operations */ - wait_queue_head_t waitqueue; - - /* The 'name' of the port that we expose via sysfs properties */ - char *name; - - /* The 'id' to identify the port with the Host */ - u32 id; - - /* Is the host device open */ - bool host_connected; - - /* We should allow only one process to open a port */ - bool guest_connected; -}; - -/* This is the very early arch-specified put chars function. */ -static int (*early_put_chars)(u32, const char *, int); - -static struct port *find_port_by_vtermno(u32 vtermno) -{ - struct port *port; - struct console *cons; - unsigned long flags; - - spin_lock_irqsave(&pdrvdata_lock, flags); - list_for_each_entry(cons, &pdrvdata.consoles, list) { - if (cons->vtermno == vtermno) { - port = container_of(cons, struct port, cons); - goto out; - } - } - port = NULL; -out: - spin_unlock_irqrestore(&pdrvdata_lock, flags); - return port; -} - -static struct port *find_port_by_id(struct ports_device *portdev, u32 id) -{ - struct port *port; - unsigned long flags; - - spin_lock_irqsave(&portdev->ports_lock, flags); - list_for_each_entry(port, &portdev->ports, list) - if (port->id == id) - goto out; - port = NULL; -out: - spin_unlock_irqrestore(&portdev->ports_lock, flags); - - return port; -} - -static struct port *find_port_by_vq(struct ports_device *portdev, - struct virtqueue *vq) -{ - struct port *port; - unsigned long flags; - - spin_lock_irqsave(&portdev->ports_lock, flags); - list_for_each_entry(port, &portdev->ports, list) - if (port->in_vq == vq || port->out_vq == vq) - goto out; - port = NULL; -out: - spin_unlock_irqrestore(&portdev->ports_lock, flags); - return port; -} - -static bool is_console_port(struct port *port) -{ - if (port->cons.hvc) - return true; - return false; -} - -static inline bool use_multiport(struct ports_device *portdev) -{ - /* - * This condition can be true when put_chars is called from - * early_init - */ - if (!portdev->vdev) - return 0; - return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); -} +/*D:340 These represent our input and output console queues, and the virtio + * operations for them. */ +static struct virtqueue *in_vq, *out_vq; +static struct virtio_device *vdev; -static void free_buf(struct port_buffer *buf) -{ - kfree(buf->buf); - kfree(buf); -} - -static struct port_buffer *alloc_buf(size_t buf_size) -{ - struct port_buffer *buf; +/* This is our input buffer, and how much data is left in it. */ +static unsigned int in_len; +static char *in, *inbuf; - buf = kmalloc(sizeof(*buf), GFP_KERNEL); - if (!buf) - goto fail; - buf->buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf->buf) - goto free_buf; - buf->len = 0; - buf->offset = 0; - buf->size = buf_size; - return buf; - -free_buf: - kfree(buf); -fail: - return NULL; -} - -/* Callers should take appropriate locks */ -static void *get_inbuf(struct port *port) -{ - struct port_buffer *buf; - struct virtqueue *vq; - unsigned int len; +/* The operations for our console. */ +static struct hv_ops virtio_cons; - vq = port->in_vq; - buf = vq->vq_ops->get_buf(vq, &len); - if (buf) { - buf->len = len; - buf->offset = 0; - } - return buf; -} +/* The hvc device */ +static struct hvc_struct *hvc; -/* - * Create a scatter-gather list representing our input buffer and put - * it in the queue. +/*D:310 The put_chars() callback is pretty straightforward. * - * Callers should take appropriate locks. - */ -static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) + * We turn the characters into a scatter-gather list, add it to the output + * queue and then kick the Host. Then we sit here waiting for it to finish: + * inefficient in theory, but in practice implementations will do it + * immediately (lguest's Launcher does). */ +static int put_chars(u32 vtermno, const char *buf, int count) { struct scatterlist sg[1]; - int ret; - - sg_init_one(sg, buf->buf, buf->size); - - ret = vq->vq_ops->add_buf(vq, sg, 0, 1, buf); - vq->vq_ops->kick(vq); - return ret; -} - -/* Discard any unread data this port has. Callers lockers. */ -static void discard_port_data(struct port *port) -{ - struct port_buffer *buf; - struct virtqueue *vq; unsigned int len; - int ret; - - vq = port->in_vq; - if (port->inbuf) - buf = port->inbuf; - else - buf = vq->vq_ops->get_buf(vq, &len); - - ret = 0; - while (buf) { - if (add_inbuf(vq, buf) < 0) { - ret++; - free_buf(buf); - } - buf = vq->vq_ops->get_buf(vq, &len); - } - port->inbuf = NULL; - if (ret) - dev_warn(port->dev, "Errors adding %d buffers back to vq\n", - ret); -} - -static bool port_has_data(struct port *port) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&port->inbuf_lock, flags); - if (port->inbuf) { - ret = true; - goto out; - } - port->inbuf = get_inbuf(port); - if (port->inbuf) { - ret = true; - goto out; - } - ret = false; -out: - spin_unlock_irqrestore(&port->inbuf_lock, flags); - return ret; -} - -static ssize_t send_control_msg(struct port *port, unsigned int event, - unsigned int value) -{ - struct scatterlist sg[1]; - struct virtio_console_control cpkt; - struct virtqueue *vq; - int len; - - if (!use_multiport(port->portdev)) - return 0; - - cpkt.id = port->id; - cpkt.event = event; - cpkt.value = value; - vq = port->portdev->c_ovq; + /* This is a convenient routine to initialize a single-elem sg list */ + sg_init_one(sg, buf, count); - sg_init_one(sg, &cpkt, sizeof(cpkt)); - if (vq->vq_ops->add_buf(vq, sg, 1, 0, &cpkt) >= 0) { - vq->vq_ops->kick(vq); - while (!vq->vq_ops->get_buf(vq, &len)) + /* add_buf wants a token to identify this buffer: we hand it any + * non-NULL pointer, since there's only ever one buffer. */ + if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) >= 0) { + /* Tell Host to go! */ + out_vq->vq_ops->kick(out_vq); + /* Chill out until it's done with the buffer. */ + while (!out_vq->vq_ops->get_buf(out_vq, &len)) cpu_relax(); } - return 0; -} - -static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count) -{ - struct scatterlist sg[1]; - struct virtqueue *out_vq; - ssize_t ret; - unsigned int len; - - out_vq = port->out_vq; - sg_init_one(sg, in_buf, in_count); - ret = out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, in_buf); - - /* Tell Host to go! */ - out_vq->vq_ops->kick(out_vq); - - if (ret < 0) { - len = 0; - goto fail; - } - - /* - * Wait till the host acknowledges it pushed out the data we - * sent. Also ensure we return to userspace the number of - * bytes that were successfully consumed by the host. - */ - while (!out_vq->vq_ops->get_buf(out_vq, &len)) - cpu_relax(); -fail: - /* We're expected to return the amount of data we wrote */ - return len; + /* We're expected to return the amount of data we wrote: all of it. */ + return count; } -/* - * Give out the data that's requested from the buffer that we have - * queued up. - */ -static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, - bool to_user) +/* Create a scatter-gather list representing our input buffer and put it in the + * queue. */ +static void add_inbuf(void) { - struct port_buffer *buf; - unsigned long flags; - - if (!out_count || !port_has_data(port)) - return 0; - - buf = port->inbuf; - out_count = min(out_count, buf->len - buf->offset); - - if (to_user) { - ssize_t ret; - - ret = copy_to_user(out_buf, buf->buf + buf->offset, out_count); - if (ret) - return -EFAULT; - } else { - memcpy(out_buf, buf->buf + buf->offset, out_count); - } - - buf->offset += out_count; - - if (buf->offset == buf->len) { - /* - * We're done using all the data in this buffer. - * Re-queue so that the Host can send us more data. - */ - spin_lock_irqsave(&port->inbuf_lock, flags); - port->inbuf = NULL; - - if (add_inbuf(port->in_vq, buf) < 0) - dev_warn(port->dev, "failed add_buf\n"); - - spin_unlock_irqrestore(&port->inbuf_lock, flags); - } - /* Return the number of bytes actually copied */ - return out_count; -} + struct scatterlist sg[1]; + sg_init_one(sg, inbuf, PAGE_SIZE); -/* The condition that must be true for polling to end */ -static bool wait_is_over(struct port *port) -{ - return port_has_data(port) || !port->host_connected; + /* We should always be able to add one buffer to an empty queue. */ + if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) < 0) + BUG(); + in_vq->vq_ops->kick(in_vq); } -static ssize_t port_fops_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *offp) +/*D:350 get_chars() is the callback from the hvc_console infrastructure when + * an interrupt is received. + * + * Most of the code deals with the fact that the hvc_console() infrastructure + * only asks us for 16 bytes at a time. We keep in_offset and in_used fields + * for partially-filled buffers. */ +static int get_chars(u32 vtermno, char *buf, int count) { - struct port *port; - ssize_t ret; - - port = filp->private_data; + /* If we don't have an input queue yet, we can't get input. */ + BUG_ON(!in_vq); - if (!port_has_data(port)) { - /* - * If nothing's connected on the host just return 0 in - * case of list_empty; this tells the userspace app - * that there's no connection - */ - if (!port->host_connected) + /* No buffer? Try to get one. */ + if (!in_len) { + in = in_vq->vq_ops->get_buf(in_vq, &in_len); + if (!in) return 0; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - - ret = wait_event_interruptible(port->waitqueue, - wait_is_over(port)); - if (ret < 0) - return ret; - } - /* - * We could've received a disconnection message while we were - * waiting for more data. - * - * This check is not clubbed in the if() statement above as we - * might receive some data as well as the host could get - * disconnected after we got woken up from our wait. So we - * really want to give off whatever data we have and only then - * check for host_connected. - */ - if (!port_has_data(port) && !port->host_connected) - return 0; - - return fill_readbuf(port, ubuf, count, true); -} - -static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, - size_t count, loff_t *offp) -{ - struct port *port; - char *buf; - ssize_t ret; - - port = filp->private_data; - - count = min((size_t)(32 * 1024), count); - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = copy_from_user(buf, ubuf, count); - if (ret) { - ret = -EFAULT; - goto free_buf; } - ret = send_buf(port, buf, count); -free_buf: - kfree(buf); - return ret; -} - -static unsigned int port_fops_poll(struct file *filp, poll_table *wait) -{ - struct port *port; - unsigned int ret; - - port = filp->private_data; - poll_wait(filp, &port->waitqueue, wait); - - ret = 0; - if (port->inbuf) - ret |= POLLIN | POLLRDNORM; - if (port->host_connected) - ret |= POLLOUT; - if (!port->host_connected) - ret |= POLLHUP; - - return ret; -} - -static int port_fops_release(struct inode *inode, struct file *filp) -{ - struct port *port; - - port = filp->private_data; - - /* Notify host of port being closed */ - send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); - - spin_lock_irq(&port->inbuf_lock); - port->guest_connected = false; - - discard_port_data(port); - - spin_unlock_irq(&port->inbuf_lock); - - return 0; -} - -static int port_fops_open(struct inode *inode, struct file *filp) -{ - struct cdev *cdev = inode->i_cdev; - struct port *port; - - port = container_of(cdev, struct port, cdev); - filp->private_data = port; - - /* - * Don't allow opening of console port devices -- that's done - * via /dev/hvc - */ - if (is_console_port(port)) - return -ENXIO; - - /* Allow only one process to open a particular port at a time */ - spin_lock_irq(&port->inbuf_lock); - if (port->guest_connected) { - spin_unlock_irq(&port->inbuf_lock); - return -EMFILE; - } + /* You want more than we have to give? Well, try wanting less! */ + if (in_len < count) + count = in_len; - port->guest_connected = true; - spin_unlock_irq(&port->inbuf_lock); + /* Copy across to their buffer and increment offset. */ + memcpy(buf, in, count); + in += count; + in_len -= count; - /* Notify host of port being opened */ - send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); + /* Finished? Re-register buffer so Host will use it again. */ + if (in_len == 0) + add_inbuf(); - return 0; + return count; } +/*:*/ -/* - * The file operations that we support: programs in the guest can open - * a console device, read from it, write to it, poll for data and - * close it. The devices are at - * /dev/vportp - */ -static const struct file_operations port_fops = { - .owner = THIS_MODULE, - .open = port_fops_open, - .read = port_fops_read, - .write = port_fops_write, - .poll = port_fops_poll, - .release = port_fops_release, -}; - -/* - * The put_chars() callback is pretty straightforward. +/*D:320 Console drivers are initialized very early so boot messages can go out, + * so we do things slightly differently from the generic virtio initialization + * of the net and block drivers. * - * We turn the characters into a scatter-gather list, add it to the - * output queue and then kick the Host. Then we sit here waiting for - * it to finish: inefficient in theory, but in practice - * implementations will do it immediately (lguest's Launcher does). - */ -static int put_chars(u32 vtermno, const char *buf, int count) + * At this stage, the console is output-only. It's too early to set up a + * virtqueue, so we let the drivers do some boutique early-output thing. */ +int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) { - struct port *port; - - port = find_port_by_vtermno(vtermno); - if (!port) - return 0; - - if (unlikely(early_put_chars)) - return early_put_chars(vtermno, buf, count); - - return send_buf(port, (void *)buf, count); + virtio_cons.put_chars = put_chars; + return hvc_instantiate(0, 0, &virtio_cons); } /* - * get_chars() is the callback from the hvc_console infrastructure - * when an interrupt is received. - * - * We call out to fill_readbuf that gets us the required data from the - * buffers that are queued up. + * virtio console configuration. This supports: + * - console resize */ -static int get_chars(u32 vtermno, char *buf, int count) +static void virtcons_apply_config(struct virtio_device *dev) { - struct port *port; - - port = find_port_by_vtermno(vtermno); - if (!port) - return 0; - - /* If we don't have an input queue yet, we can't get input. */ - BUG_ON(!port->in_vq); - - return fill_readbuf(port, buf, count, false); -} - -static void resize_console(struct port *port) -{ - struct virtio_device *vdev; struct winsize ws; - vdev = port->portdev->vdev; - if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) { - vdev->config->get(vdev, - offsetof(struct virtio_console_config, cols), - &ws.ws_col, sizeof(u16)); - vdev->config->get(vdev, - offsetof(struct virtio_console_config, rows), - &ws.ws_row, sizeof(u16)); - hvc_resize(port->cons.hvc, ws); + if (virtio_has_feature(dev, VIRTIO_CONSOLE_F_SIZE)) { + dev->config->get(dev, + offsetof(struct virtio_console_config, cols), + &ws.ws_col, sizeof(u16)); + dev->config->get(dev, + offsetof(struct virtio_console_config, rows), + &ws.ws_row, sizeof(u16)); + hvc_resize(hvc, ws); } } -/* We set the configuration at this point, since we now have a tty */ +/* + * we support only one console, the hvc struct is a global var + * We set the configuration at this point, since we now have a tty + */ static int notifier_add_vio(struct hvc_struct *hp, int data) { - struct port *port; - - port = find_port_by_vtermno(hp->vtermno); - if (!port) - return -EINVAL; - hp->irq_requested = 1; - resize_console(port); + virtcons_apply_config(vdev); return 0; } @@ -713,797 +173,79 @@ static void notifier_del_vio(struct hvc_struct *hp, int data) hp->irq_requested = 0; } -/* The operations for console ports. */ -static const struct hv_ops hv_ops = { - .get_chars = get_chars, - .put_chars = put_chars, - .notifier_add = notifier_add_vio, - .notifier_del = notifier_del_vio, - .notifier_hangup = notifier_del_vio, -}; - -/* - * Console drivers are initialized very early so boot messages can go - * out, so we do things slightly differently from the generic virtio - * initialization of the net and block drivers. - * - * At this stage, the console is output-only. It's too early to set - * up a virtqueue, so we let the drivers do some boutique early-output - * thing. - */ -int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) +static void hvc_handle_input(struct virtqueue *vq) { - early_put_chars = put_chars; - return hvc_instantiate(0, 0, &hv_ops); -} - -int init_port_console(struct port *port) -{ - int ret; - - /* - * The Host's telling us this port is a console port. Hook it - * up with an hvc console. - * - * To set up and manage our virtual console, we call - * hvc_alloc(). - * - * The first argument of hvc_alloc() is the virtual console - * number. The second argument is the parameter for the - * notification mechanism (like irq number). We currently - * leave this as zero, virtqueues have implicit notifications. - * - * The third argument is a "struct hv_ops" containing the - * put_chars() get_chars(), notifier_add() and notifier_del() - * pointers. The final argument is the output buffer size: we - * can do any size, so we put PAGE_SIZE here. - */ - port->cons.vtermno = pdrvdata.next_vtermno; - - port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE); - if (IS_ERR(port->cons.hvc)) { - ret = PTR_ERR(port->cons.hvc); - dev_err(port->dev, - "error %d allocating hvc for port\n", ret); - port->cons.hvc = NULL; - return ret; - } - spin_lock_irq(&pdrvdata_lock); - pdrvdata.next_vtermno++; - list_add_tail(&port->cons.list, &pdrvdata.consoles); - spin_unlock_irq(&pdrvdata_lock); - port->guest_connected = true; - - /* Notify host of port being opened */ - send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); - - return 0; -} - -static ssize_t show_port_name(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - struct port *port; - - port = dev_get_drvdata(dev); - - return sprintf(buffer, "%s\n", port->name); -} - -static DEVICE_ATTR(name, S_IRUGO, show_port_name, NULL); - -static struct attribute *port_sysfs_entries[] = { - &dev_attr_name.attr, - NULL -}; - -static struct attribute_group port_attribute_group = { - .name = NULL, /* put in device directory */ - .attrs = port_sysfs_entries, -}; - -static int debugfs_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - -static ssize_t debugfs_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *offp) -{ - struct port *port; - char *buf; - ssize_t ret, out_offset, out_count; - - out_count = 1024; - buf = kmalloc(out_count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - port = filp->private_data; - out_offset = 0; - out_offset += snprintf(buf + out_offset, out_count, - "name: %s\n", port->name ? port->name : ""); - out_offset += snprintf(buf + out_offset, out_count - out_offset, - "guest_connected: %d\n", port->guest_connected); - out_offset += snprintf(buf + out_offset, out_count - out_offset, - "host_connected: %d\n", port->host_connected); - out_offset += snprintf(buf + out_offset, out_count - out_offset, - "is_console: %s\n", - is_console_port(port) ? "yes" : "no"); - out_offset += snprintf(buf + out_offset, out_count - out_offset, - "console_vtermno: %u\n", port->cons.vtermno); - - ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset); - kfree(buf); - return ret; -} - -static const struct file_operations port_debugfs_ops = { - .owner = THIS_MODULE, - .open = debugfs_open, - .read = debugfs_read, -}; - -/* Remove all port-specific data. */ -static int remove_port(struct port *port) -{ - struct port_buffer *buf; - - spin_lock_irq(&port->portdev->ports_lock); - list_del(&port->list); - spin_unlock_irq(&port->portdev->ports_lock); - - if (is_console_port(port)) { - spin_lock_irq(&pdrvdata_lock); - list_del(&port->cons.list); - spin_unlock_irq(&pdrvdata_lock); - hvc_remove(port->cons.hvc); - } - if (port->guest_connected) - send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); - - sysfs_remove_group(&port->dev->kobj, &port_attribute_group); - device_destroy(pdrvdata.class, port->dev->devt); - cdev_del(&port->cdev); - - /* Remove unused data this port might have received. */ - discard_port_data(port); - - /* Remove buffers we queued up for the Host to send us data in. */ - while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq))) - free_buf(buf); - - kfree(port->name); - - debugfs_remove(port->debugfs_file); - - kfree(port); - return 0; -} - -/* Any private messages that the Host and Guest want to share */ -static void handle_control_message(struct ports_device *portdev, - struct port_buffer *buf) -{ - struct virtio_console_control *cpkt; - struct port *port; - size_t name_size; - int err; - - cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); - - port = find_port_by_id(portdev, cpkt->id); - if (!port) { - /* No valid header at start of buffer. Drop it. */ - dev_dbg(&portdev->vdev->dev, - "Invalid index %u in control packet\n", cpkt->id); - return; - } - - switch (cpkt->event) { - case VIRTIO_CONSOLE_CONSOLE_PORT: - if (!cpkt->value) - break; - if (is_console_port(port)) - break; - - init_port_console(port); - /* - * Could remove the port here in case init fails - but - * have to notify the host first. - */ - break; - case VIRTIO_CONSOLE_RESIZE: - if (!is_console_port(port)) - break; - port->cons.hvc->irq_requested = 1; - resize_console(port); - break; - case VIRTIO_CONSOLE_PORT_OPEN: - port->host_connected = cpkt->value; - wake_up_interruptible(&port->waitqueue); - break; - case VIRTIO_CONSOLE_PORT_NAME: - /* - * Skip the size of the header and the cpkt to get the size - * of the name that was sent - */ - name_size = buf->len - buf->offset - sizeof(*cpkt) + 1; - - port->name = kmalloc(name_size, GFP_KERNEL); - if (!port->name) { - dev_err(port->dev, - "Not enough space to store port name\n"); - break; - } - strncpy(port->name, buf->buf + buf->offset + sizeof(*cpkt), - name_size - 1); - port->name[name_size - 1] = 0; - - /* - * Since we only have one sysfs attribute, 'name', - * create it only if we have a name for the port. - */ - err = sysfs_create_group(&port->dev->kobj, - &port_attribute_group); - if (err) - dev_err(port->dev, - "Error %d creating sysfs device attributes\n", - err); - - break; - case VIRTIO_CONSOLE_PORT_REMOVE: - /* - * Hot unplug the port. We don't decrement nr_ports - * since we don't want to deal with extra complexities - * of using the lowest-available port id: We can just - * pick up the nr_ports number as the id and not have - * userspace send it to us. This helps us in two - * ways: - * - * - We don't need to have a 'port_id' field in the - * config space when a port is hot-added. This is a - * good thing as we might queue up multiple hotplug - * requests issued in our workqueue. - * - * - Another way to deal with this would have been to - * use a bitmap of the active ports and select the - * lowest non-active port from that map. That - * bloats the already tight config space and we - * would end up artificially limiting the - * max. number of ports to sizeof(bitmap). Right - * now we can support 2^32 ports (as the port id is - * stored in a u32 type). - * - */ - remove_port(port); - break; - } -} - -static void control_work_handler(struct work_struct *work) -{ - struct ports_device *portdev; - struct virtqueue *vq; - struct port_buffer *buf; - unsigned int len; - - portdev = container_of(work, struct ports_device, control_work); - vq = portdev->c_ivq; - - spin_lock(&portdev->cvq_lock); - while ((buf = vq->vq_ops->get_buf(vq, &len))) { - spin_unlock(&portdev->cvq_lock); - - buf->len = len; - buf->offset = 0; - - handle_control_message(portdev, buf); - - spin_lock(&portdev->cvq_lock); - if (add_inbuf(portdev->c_ivq, buf) < 0) { - dev_warn(&portdev->vdev->dev, - "Error adding buffer to queue\n"); - free_buf(buf); - } - } - spin_unlock(&portdev->cvq_lock); -} - -static void in_intr(struct virtqueue *vq) -{ - struct port *port; - unsigned long flags; - - port = find_port_by_vq(vq->vdev->priv, vq); - if (!port) - return; - - spin_lock_irqsave(&port->inbuf_lock, flags); - if (!port->inbuf) - port->inbuf = get_inbuf(port); - - /* - * Don't queue up data when port is closed. This condition - * can be reached when a console port is not yet connected (no - * tty is spawned) and the host sends out data to console - * ports. For generic serial ports, the host won't - * (shouldn't) send data till the guest is connected. - */ - if (!port->guest_connected) - discard_port_data(port); - - spin_unlock_irqrestore(&port->inbuf_lock, flags); - - wake_up_interruptible(&port->waitqueue); - - if (is_console_port(port) && hvc_poll(port->cons.hvc)) + if (hvc_poll(hvc)) hvc_kick(); } -static void control_intr(struct virtqueue *vq) -{ - struct ports_device *portdev; - - portdev = vq->vdev->priv; - schedule_work(&portdev->control_work); -} - -static void config_intr(struct virtio_device *vdev) -{ - struct ports_device *portdev; - - portdev = vdev->priv; - if (use_multiport(portdev)) { - /* Handle port hot-add */ - schedule_work(&portdev->config_work); - } - /* - * We'll use this way of resizing only for legacy support. - * For newer userspace (VIRTIO_CONSOLE_F_MULTPORT+), use - * control messages to indicate console size changes so that - * it can be done per-port - */ - resize_console(find_port_by_id(portdev, 0)); -} - -static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) -{ - struct port_buffer *buf; - unsigned int ret; - int err; - - ret = 0; - do { - buf = alloc_buf(PAGE_SIZE); - if (!buf) - break; - - spin_lock_irq(lock); - err = add_inbuf(vq, buf); - if (err < 0) { - spin_unlock_irq(lock); - free_buf(buf); - break; - } - ret++; - spin_unlock_irq(lock); - } while (err > 0); - - return ret; -} - -static int add_port(struct ports_device *portdev, u32 id) -{ - char debugfs_name[16]; - struct port *port; - struct port_buffer *buf; - dev_t devt; - int err; - - port = kmalloc(sizeof(*port), GFP_KERNEL); - if (!port) { - err = -ENOMEM; - goto fail; - } - - port->portdev = portdev; - port->id = id; - - port->name = NULL; - port->inbuf = NULL; - port->cons.hvc = NULL; - - port->host_connected = port->guest_connected = false; - - port->in_vq = portdev->in_vqs[port->id]; - port->out_vq = portdev->out_vqs[port->id]; - - cdev_init(&port->cdev, &port_fops); - - devt = MKDEV(portdev->chr_major, id); - err = cdev_add(&port->cdev, devt, 1); - if (err < 0) { - dev_err(&port->portdev->vdev->dev, - "Error %d adding cdev for port %u\n", err, id); - goto free_port; - } - port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, - devt, port, "vport%up%u", - port->portdev->drv_index, id); - if (IS_ERR(port->dev)) { - err = PTR_ERR(port->dev); - dev_err(&port->portdev->vdev->dev, - "Error %d creating device for port %u\n", - err, id); - goto free_cdev; - } - - spin_lock_init(&port->inbuf_lock); - init_waitqueue_head(&port->waitqueue); - - /* Fill the in_vq with buffers so the host can send us data. */ - err = fill_queue(port->in_vq, &port->inbuf_lock); - if (!err) { - dev_err(port->dev, "Error allocating inbufs\n"); - err = -ENOMEM; - goto free_device; - } - - /* - * If we're not using multiport support, this has to be a console port - */ - if (!use_multiport(port->portdev)) { - err = init_port_console(port); - if (err) - goto free_inbufs; - } - - spin_lock_irq(&portdev->ports_lock); - list_add_tail(&port->list, &port->portdev->ports); - spin_unlock_irq(&portdev->ports_lock); - - /* - * Tell the Host we're set so that it can send us various - * configuration parameters for this port (eg, port name, - * caching, whether this is a console port, etc.) - */ - send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); - - if (pdrvdata.debugfs_dir) { - /* - * Finally, create the debugfs file that we can use to - * inspect a port's state at any time - */ - sprintf(debugfs_name, "vport%up%u", - port->portdev->drv_index, id); - port->debugfs_file = debugfs_create_file(debugfs_name, 0444, - pdrvdata.debugfs_dir, - port, - &port_debugfs_ops); - } - return 0; - -free_inbufs: - while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq))) - free_buf(buf); -free_device: - device_destroy(pdrvdata.class, port->dev->devt); -free_cdev: - cdev_del(&port->cdev); -free_port: - kfree(port); -fail: - return err; -} - -/* - * The workhandler for config-space updates. +/*D:370 Once we're further in boot, we get probed like any other virtio device. + * At this stage we set up the output virtqueue. * - * This is called when ports are hot-added. - */ -static void config_work_handler(struct work_struct *work) -{ - struct virtio_console_config virtconconf; - struct ports_device *portdev; - struct virtio_device *vdev; - int err; - - portdev = container_of(work, struct ports_device, config_work); - - vdev = portdev->vdev; - vdev->config->get(vdev, - offsetof(struct virtio_console_config, nr_ports), - &virtconconf.nr_ports, - sizeof(virtconconf.nr_ports)); - - if (portdev->config.nr_ports == virtconconf.nr_ports) { - /* - * Port 0 got hot-added. Since we already did all the - * other initialisation for it, just tell the Host - * that the port is ready if we find the port. In - * case the port was hot-removed earlier, we call - * add_port to add the port. - */ - struct port *port; - - port = find_port_by_id(portdev, 0); - if (!port) - add_port(portdev, 0); - else - send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); - return; - } - if (virtconconf.nr_ports > portdev->config.max_nr_ports) { - dev_warn(&vdev->dev, - "More ports specified (%u) than allowed (%u)", - portdev->config.nr_ports + 1, - portdev->config.max_nr_ports); - return; - } - if (virtconconf.nr_ports < portdev->config.nr_ports) - return; - - /* Hot-add ports */ - while (virtconconf.nr_ports - portdev->config.nr_ports) { - err = add_port(portdev, portdev->config.nr_ports); - if (err) - break; - portdev->config.nr_ports++; - } -} - -static int init_vqs(struct ports_device *portdev) + * To set up and manage our virtual console, we call hvc_alloc(). Since we + * never remove the console device we never need this pointer again. + * + * Finally we put our input buffer in the input queue, ready to receive. */ +static int __devinit virtcons_probe(struct virtio_device *dev) { - vq_callback_t **io_callbacks; - char **io_names; - struct virtqueue **vqs; - u32 i, j, nr_ports, nr_queues; + vq_callback_t *callbacks[] = { hvc_handle_input, NULL}; + const char *names[] = { "input", "output" }; + struct virtqueue *vqs[2]; int err; - nr_ports = portdev->config.max_nr_ports; - nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2; + vdev = dev; - vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL); - if (!vqs) { + /* This is the scratch page we use to receive console input */ + inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!inbuf) { err = -ENOMEM; goto fail; } - io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL); - if (!io_callbacks) { - err = -ENOMEM; - goto free_vqs; - } - io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL); - if (!io_names) { - err = -ENOMEM; - goto free_callbacks; - } - portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), - GFP_KERNEL); - if (!portdev->in_vqs) { - err = -ENOMEM; - goto free_names; - } - portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), - GFP_KERNEL); - if (!portdev->out_vqs) { - err = -ENOMEM; - goto free_invqs; - } - - /* - * For backward compat (newer host but older guest), the host - * spawns a console port first and also inits the vqs for port - * 0 before others. - */ - j = 0; - io_callbacks[j] = in_intr; - io_callbacks[j + 1] = NULL; - io_names[j] = "input"; - io_names[j + 1] = "output"; - j += 2; - if (use_multiport(portdev)) { - io_callbacks[j] = control_intr; - io_callbacks[j + 1] = NULL; - io_names[j] = "control-i"; - io_names[j + 1] = "control-o"; - - for (i = 1; i < nr_ports; i++) { - j += 2; - io_callbacks[j] = in_intr; - io_callbacks[j + 1] = NULL; - io_names[j] = "input"; - io_names[j + 1] = "output"; - } - } /* Find the queues. */ - err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs, - io_callbacks, - (const char **)io_names); + /* FIXME: This is why we want to wean off hvc: we do nothing + * when input comes in. */ + err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); if (err) - goto free_outvqs; - - j = 0; - portdev->in_vqs[0] = vqs[0]; - portdev->out_vqs[0] = vqs[1]; - j += 2; - if (use_multiport(portdev)) { - portdev->c_ivq = vqs[j]; - portdev->c_ovq = vqs[j + 1]; - - for (i = 1; i < nr_ports; i++) { - j += 2; - portdev->in_vqs[i] = vqs[j]; - portdev->out_vqs[i] = vqs[j + 1]; - } - } - kfree(io_callbacks); - kfree(io_names); - kfree(vqs); - - return 0; - -free_names: - kfree(io_names); -free_callbacks: - kfree(io_callbacks); -free_outvqs: - kfree(portdev->out_vqs); -free_invqs: - kfree(portdev->in_vqs); -free_vqs: - kfree(vqs); -fail: - return err; -} - -static const struct file_operations portdev_fops = { - .owner = THIS_MODULE, -}; - -/* - * Once we're further in boot, we get probed like any other virtio - * device. - * - * If the host also supports multiple console ports, we check the - * config space to see how many ports the host has spawned. We - * initialize each port found. - */ -static int __devinit virtcons_probe(struct virtio_device *vdev) -{ - struct ports_device *portdev; - u32 i; - int err; - bool multiport; - - portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); - if (!portdev) { - err = -ENOMEM; - goto fail; - } - - /* Attach this portdev to this virtio_device, and vice-versa. */ - portdev->vdev = vdev; - vdev->priv = portdev; - - spin_lock_irq(&pdrvdata_lock); - portdev->drv_index = pdrvdata.index++; - spin_unlock_irq(&pdrvdata_lock); - - portdev->chr_major = register_chrdev(0, "virtio-portsdev", - &portdev_fops); - if (portdev->chr_major < 0) { - dev_err(&vdev->dev, - "Error %d registering chrdev for device %u\n", - portdev->chr_major, portdev->drv_index); - err = portdev->chr_major; goto free; - } - multiport = false; - portdev->config.nr_ports = 1; - portdev->config.max_nr_ports = 1; - if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { - multiport = true; - vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; + in_vq = vqs[0]; + out_vq = vqs[1]; - vdev->config->get(vdev, offsetof(struct virtio_console_config, - nr_ports), - &portdev->config.nr_ports, - sizeof(portdev->config.nr_ports)); - vdev->config->get(vdev, offsetof(struct virtio_console_config, - max_nr_ports), - &portdev->config.max_nr_ports, - sizeof(portdev->config.max_nr_ports)); - if (portdev->config.nr_ports > portdev->config.max_nr_ports) { - dev_warn(&vdev->dev, - "More ports (%u) specified than allowed (%u). Will init %u ports.", - portdev->config.nr_ports, - portdev->config.max_nr_ports, - portdev->config.max_nr_ports); - - portdev->config.nr_ports = portdev->config.max_nr_ports; - } - } - - /* Let the Host know we support multiple ports.*/ - vdev->config->finalize_features(vdev); - - err = init_vqs(portdev); - if (err < 0) { - dev_err(&vdev->dev, "Error %d initializing vqs\n", err); - goto free_chrdev; - } - - spin_lock_init(&portdev->ports_lock); - INIT_LIST_HEAD(&portdev->ports); - - if (multiport) { - spin_lock_init(&portdev->cvq_lock); - INIT_WORK(&portdev->control_work, &control_work_handler); - INIT_WORK(&portdev->config_work, &config_work_handler); - - err = fill_queue(portdev->c_ivq, &portdev->cvq_lock); - if (!err) { - dev_err(&vdev->dev, - "Error allocating buffers for control queue\n"); - err = -ENOMEM; - goto free_vqs; - } + /* Start using the new console output. */ + virtio_cons.get_chars = get_chars; + virtio_cons.put_chars = put_chars; + virtio_cons.notifier_add = notifier_add_vio; + virtio_cons.notifier_del = notifier_del_vio; + virtio_cons.notifier_hangup = notifier_del_vio; + + /* The first argument of hvc_alloc() is the virtual console number, so + * we use zero. The second argument is the parameter for the + * notification mechanism (like irq number). We currently leave this + * as zero, virtqueues have implicit notifications. + * + * The third argument is a "struct hv_ops" containing the put_chars() + * get_chars(), notifier_add() and notifier_del() pointers. + * The final argument is the output buffer size: we can do any size, + * so we put PAGE_SIZE here. */ + hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); + if (IS_ERR(hvc)) { + err = PTR_ERR(hvc); + goto free_vqs; } - for (i = 0; i < portdev->config.nr_ports; i++) - add_port(portdev, i); - - /* Start using the new console output. */ - early_put_chars = NULL; + /* Register the input buffer the first time. */ + add_inbuf(); return 0; free_vqs: vdev->config->del_vqs(vdev); - kfree(portdev->in_vqs); - kfree(portdev->out_vqs); -free_chrdev: - unregister_chrdev(portdev->chr_major, "virtio-portsdev"); free: - kfree(portdev); + kfree(inbuf); fail: return err; } -static void virtcons_remove(struct virtio_device *vdev) -{ - struct ports_device *portdev; - struct port *port, *port2; - struct port_buffer *buf; - unsigned int len; - - portdev = vdev->priv; - - cancel_work_sync(&portdev->control_work); - cancel_work_sync(&portdev->config_work); - - list_for_each_entry_safe(port, port2, &portdev->ports, list) - remove_port(port); - - unregister_chrdev(portdev->chr_major, "virtio-portsdev"); - - while ((buf = portdev->c_ivq->vq_ops->get_buf(portdev->c_ivq, &len))) - free_buf(buf); - - while ((buf = portdev->c_ivq->vq_ops->detach_unused_buf(portdev->c_ivq))) - free_buf(buf); - - vdev->config->del_vqs(vdev); - kfree(portdev->in_vqs); - kfree(portdev->out_vqs); - - kfree(portdev); -} - static struct virtio_device_id id_table[] = { { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID }, { 0 }, @@ -1511,7 +253,6 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_CONSOLE_F_SIZE, - VIRTIO_CONSOLE_F_MULTIPORT, }; static struct virtio_driver virtio_console = { @@ -1521,41 +262,14 @@ static struct virtio_driver virtio_console = { .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtcons_probe, - .remove = virtcons_remove, - .config_changed = config_intr, + .config_changed = virtcons_apply_config, }; static int __init init(void) { - int err; - - pdrvdata.class = class_create(THIS_MODULE, "virtio-ports"); - if (IS_ERR(pdrvdata.class)) { - err = PTR_ERR(pdrvdata.class); - pr_err("Error %d creating virtio-ports class\n", err); - return err; - } - - pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); - if (!pdrvdata.debugfs_dir) { - pr_warning("Error %ld creating debugfs dir for virtio-ports\n", - PTR_ERR(pdrvdata.debugfs_dir)); - } - INIT_LIST_HEAD(&pdrvdata.consoles); - return register_virtio_driver(&virtio_console); } - -static void __exit fini(void) -{ - unregister_virtio_driver(&virtio_console); - - class_destroy(pdrvdata.class); - if (pdrvdata.debugfs_dir) - debugfs_remove_recursive(pdrvdata.debugfs_dir); -} module_init(init); -module_exit(fini); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Virtio console driver"); diff --git a/trunk/drivers/clocksource/cs5535-clockevt.c b/trunk/drivers/clocksource/cs5535-clockevt.c index b314a999aabe..27d20fac19d1 100644 --- a/trunk/drivers/clocksource/cs5535-clockevt.c +++ b/trunk/drivers/clocksource/cs5535-clockevt.c @@ -21,7 +21,7 @@ #define DRV_NAME "cs5535-clockevt" -static int timer_irq; +static int timer_irq = CONFIG_CS5535_MFGPT_DEFAULT_IRQ; module_param_named(irq, timer_irq, int, 0644); MODULE_PARM_DESC(irq, "Which IRQ to use for the clock source MFGPT ticks."); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h index 1c15ef37b71c..5445cefdd03e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -583,7 +583,6 @@ struct drm_nouveau_private { uint64_t vm_end; struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; int vm_vram_pt_nr; - uint64_t vram_sys_base; /* the mtrr covering the FB */ int fb_mtrr; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c b/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c index 2dc09dbd817d..8f3a12f614ed 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -285,50 +285,53 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, uint32_t flags, uint64_t phys) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *pgt; - unsigned block; - int i; - - virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1; - size = (size >> 16) << 1; - - phys |= ((uint64_t)flags << 32); - phys |= 1; - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; - phys |= 0x30; + struct nouveau_gpuobj **pgt; + unsigned psz, pfl, pages; + + if (virt >= dev_priv->vm_gart_base && + (virt + size) < (dev_priv->vm_gart_base + dev_priv->vm_gart_size)) { + psz = 12; + pgt = &dev_priv->gart_info.sg_ctxdma; + pfl = 0x21; + virt -= dev_priv->vm_gart_base; + } else + if (virt >= dev_priv->vm_vram_base && + (virt + size) < (dev_priv->vm_vram_base + dev_priv->vm_vram_size)) { + psz = 16; + pgt = dev_priv->vm_vram_pt; + pfl = 0x01; + virt -= dev_priv->vm_vram_base; + } else { + NV_ERROR(dev, "Invalid address: 0x%16llx-0x%16llx\n", + virt, virt + size - 1); + return -EINVAL; } + pages = size >> psz; + dev_priv->engine.instmem.prepare_access(dev, true); - while (size) { - unsigned offset_h = upper_32_bits(phys); - unsigned offset_l = lower_32_bits(phys); - unsigned pte, end; - - for (i = 7; i >= 0; i--) { - block = 1 << (i + 1); - if (size >= block && !(virt & (block - 1))) - break; - } - offset_l |= (i << 7); + if (flags & 0x80000000) { + while (pages--) { + struct nouveau_gpuobj *pt = pgt[virt >> 29]; + unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1; - phys += block << 15; - size -= block; + nv_wo32(dev, pt, pte++, 0x00000000); + nv_wo32(dev, pt, pte++, 0x00000000); - while (block) { - pgt = dev_priv->vm_vram_pt[virt >> 14]; - pte = virt & 0x3ffe; + virt += (1 << psz); + } + } else { + while (pages--) { + struct nouveau_gpuobj *pt = pgt[virt >> 29]; + unsigned pte = ((virt & 0x1fffffffULL) >> psz) << 1; + unsigned offset_h = upper_32_bits(phys) & 0xff; + unsigned offset_l = lower_32_bits(phys); - end = pte + block; - if (end > 16384) - end = 16384; - block -= (end - pte); - virt += (end - pte); + nv_wo32(dev, pt, pte++, offset_l | pfl); + nv_wo32(dev, pt, pte++, offset_h | flags); - while (pte < end) { - nv_wo32(dev, pgt, pte++, offset_l); - nv_wo32(dev, pgt, pte++, offset_h); - } + phys += (1 << psz); + virt += (1 << psz); } } dev_priv->engine.instmem.finish_access(dev); @@ -353,41 +356,7 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, void nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *pgt; - unsigned pages, pte, end; - - virt -= dev_priv->vm_vram_base; - pages = (size >> 16) << 1; - - dev_priv->engine.instmem.prepare_access(dev, true); - while (pages) { - pgt = dev_priv->vm_vram_pt[virt >> 29]; - pte = (virt & 0x1ffe0000ULL) >> 15; - - end = pte + pages; - if (end > 16384) - end = 16384; - pages -= (end - pte); - virt += (end - pte) << 15; - - while (pte < end) - nv_wo32(dev, pgt, pte++, 0); - } - dev_priv->engine.instmem.finish_access(dev); - - nv_wr32(dev, 0x100c80, 0x00050001); - if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); - NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); - return; - } - - nv_wr32(dev, 0x100c80, 0x00000001); - if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { - NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); - NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); - } + nv50_mem_vm_bind_linear(dev, virt, size, 0x80000000, 0); } /* diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c index 1d73b15d70da..d0e038d28948 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c @@ -119,7 +119,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode; + uint8_t saved_seq1, saved_pi, saved_rpc1; uint8_t saved_palette0[3], saved_palette_mask; uint32_t saved_rtest_ctrl, saved_rgen_ctrl; int i; @@ -135,9 +135,6 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, /* only implemented for head A for now */ NVSetOwner(dev, 0); - saved_cr_mode = NVReadVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX); - NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode | 0x80); - saved_seq1 = NVReadVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX); NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20); @@ -206,7 +203,6 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1); - NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { NV_INFO(dev, "Load detected on head A\n"); diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_instmem.c b/trunk/drivers/gpu/drm/nouveau/nv50_instmem.c index f0dc4e36ef05..94400f777e7f 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -76,11 +76,6 @@ nv50_instmem_init(struct drm_device *dev) for (i = 0x1700; i <= 0x1710; i += 4) priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); - if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) - dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12; - else - dev_priv->vram_sys_base = 0; - /* Reserve the last MiB of VRAM, we should probably try to avoid * setting up the below tables over the top of the VBIOS image at * some point. @@ -177,28 +172,16 @@ nv50_instmem_init(struct drm_device *dev) * We map the entire fake channel into the start of the PRAMIN BAR */ ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, - 0, &priv->pramin_pt); + 0, &priv->pramin_pt); if (ret) return ret; - v = c_offset | 1; - if (dev_priv->vram_sys_base) { - v += dev_priv->vram_sys_base; - v |= 0x30; - } - - i = 0; - while (v < dev_priv->vram_sys_base + c_offset + c_size) { - BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v); - BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); - v += 0x1000; - i += 8; - } - - while (i < pt_size) { - BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000); + for (i = 0, v = c_offset; i < pt_size; i += 8, v += 0x1000) { + if (v < (c_offset + c_size)) + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); + else + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); - i += 8; } BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); @@ -433,9 +416,7 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj; - uint32_t pte, pte_end; - uint64_t vram; + uint32_t pte, pte_end, vram; if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) return -EINVAL; @@ -443,24 +424,20 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", gpuobj->im_pramin->start, gpuobj->im_pramin->size); - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; vram = gpuobj->im_backing_start; NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", gpuobj->im_pramin->start, pte, pte_end); NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); - vram |= 1; - if (dev_priv->vram_sys_base) { - vram += dev_priv->vram_sys_base; - vram |= 0x30; - } - dev_priv->engine.instmem.prepare_access(dev, true); while (pte < pte_end) { - nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); - nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + + pte += 8; vram += NV50_INSTMEM_PAGE_SIZE; } dev_priv->engine.instmem.finish_access(dev); @@ -493,13 +470,14 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) if (gpuobj->im_bound == 0) return -EINVAL; - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; + pte = (gpuobj->im_pramin->start >> 12) << 3; + pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; dev_priv->engine.instmem.prepare_access(dev, true); while (pte < pte_end) { - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); + nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); + pte += 8; } dev_priv->engine.instmem.finish_access(dev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_combios.c b/trunk/drivers/gpu/drm/radeon/radeon_combios.c index 22d476160d52..e7b19440102e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_combios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_combios.c @@ -1279,47 +1279,47 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) rdev->mode_info.connector_table = radeon_connector_table; if (rdev->mode_info.connector_table == CT_NONE) { #ifdef CONFIG_PPC_PMAC - if (of_machine_is_compatible("PowerBook3,3")) { + if (machine_is_compatible("PowerBook3,3")) { /* powerbook with VGA */ rdev->mode_info.connector_table = CT_POWERBOOK_VGA; - } else if (of_machine_is_compatible("PowerBook3,4") || - of_machine_is_compatible("PowerBook3,5")) { + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5")) { /* powerbook with internal tmds */ rdev->mode_info.connector_table = CT_POWERBOOK_INTERNAL; - } else if (of_machine_is_compatible("PowerBook5,1") || - of_machine_is_compatible("PowerBook5,2") || - of_machine_is_compatible("PowerBook5,3") || - of_machine_is_compatible("PowerBook5,4") || - of_machine_is_compatible("PowerBook5,5")) { + } else if (machine_is_compatible("PowerBook5,1") || + machine_is_compatible("PowerBook5,2") || + machine_is_compatible("PowerBook5,3") || + machine_is_compatible("PowerBook5,4") || + machine_is_compatible("PowerBook5,5")) { /* powerbook with external single link tmds (sil164) */ rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; - } else if (of_machine_is_compatible("PowerBook5,6")) { + } else if (machine_is_compatible("PowerBook5,6")) { /* powerbook with external dual or single link tmds */ rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; - } else if (of_machine_is_compatible("PowerBook5,7") || - of_machine_is_compatible("PowerBook5,8") || - of_machine_is_compatible("PowerBook5,9")) { + } else if (machine_is_compatible("PowerBook5,7") || + machine_is_compatible("PowerBook5,8") || + machine_is_compatible("PowerBook5,9")) { /* PowerBook6,2 ? */ /* powerbook with external dual link tmds (sil1178?) */ rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; - } else if (of_machine_is_compatible("PowerBook4,1") || - of_machine_is_compatible("PowerBook4,2") || - of_machine_is_compatible("PowerBook4,3") || - of_machine_is_compatible("PowerBook6,3") || - of_machine_is_compatible("PowerBook6,5") || - of_machine_is_compatible("PowerBook6,7")) { + } else if (machine_is_compatible("PowerBook4,1") || + machine_is_compatible("PowerBook4,2") || + machine_is_compatible("PowerBook4,3") || + machine_is_compatible("PowerBook6,3") || + machine_is_compatible("PowerBook6,5") || + machine_is_compatible("PowerBook6,7")) { /* ibook */ rdev->mode_info.connector_table = CT_IBOOK; - } else if (of_machine_is_compatible("PowerMac4,4")) { + } else if (machine_is_compatible("PowerMac4,4")) { /* emac */ rdev->mode_info.connector_table = CT_EMAC; - } else if (of_machine_is_compatible("PowerMac10,1")) { + } else if (machine_is_compatible("PowerMac10,1")) { /* mini with internal tmds */ rdev->mode_info.connector_table = CT_MINI_INTERNAL; - } else if (of_machine_is_compatible("PowerMac10,2")) { + } else if (machine_is_compatible("PowerMac10,2")) { /* mini with external tmds */ rdev->mode_info.connector_table = CT_MINI_EXTERNAL; - } else if (of_machine_is_compatible("PowerMac12,1")) { + } else if (machine_is_compatible("PowerMac12,1")) { /* PowerMac8,1 ? */ /* imac g5 isight */ rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 0897359b3e4e..d69caf92ffe7 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -182,19 +182,25 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid); } -static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - SVGAGuestPtr *ptr, - struct vmw_dma_buffer **vmw_bo_p) +static int vmw_cmd_dma(struct vmw_private *dev_priv, + struct vmw_sw_context *sw_context, + SVGA3dCmdHeader *header) { + uint32_t handle; struct vmw_dma_buffer *vmw_bo = NULL; struct ttm_buffer_object *bo; - uint32_t handle = ptr->gmrId; + struct vmw_surface *srf = NULL; + struct vmw_dma_cmd { + SVGA3dCmdHeader header; + SVGA3dCmdSurfaceDMA dma; + } *cmd; struct vmw_relocation *reloc; + int ret; uint32_t cur_validate_node; struct ttm_validate_buffer *val_buf; - int ret; + cmd = container_of(header, struct vmw_dma_cmd, header); + handle = cmd->dma.guest.ptr.gmrId; ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use GMR region.\n"); @@ -203,14 +209,14 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, bo = &vmw_bo->base; if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) { - DRM_ERROR("Max number relocations per submission" + DRM_ERROR("Max number of DMA commands per submission" " exceeded\n"); ret = -EINVAL; goto out_no_reloc; } reloc = &sw_context->relocs[sw_context->cur_reloc++]; - reloc->location = ptr; + reloc->location = &cmd->dma.guest.ptr; cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf); if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) { @@ -228,89 +234,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, list_add_tail(&val_buf->head, &sw_context->validate_nodes); ++sw_context->cur_val_buf; } - *vmw_bo_p = vmw_bo; - return 0; - -out_no_reloc: - vmw_dmabuf_unreference(&vmw_bo); - vmw_bo_p = NULL; - return ret; -} - -static int vmw_cmd_end_query(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - SVGA3dCmdHeader *header) -{ - struct vmw_dma_buffer *vmw_bo; - struct vmw_query_cmd { - SVGA3dCmdHeader header; - SVGA3dCmdEndQuery q; - } *cmd; - int ret; - - cmd = container_of(header, struct vmw_query_cmd, header); - ret = vmw_cmd_cid_check(dev_priv, sw_context, header); - if (unlikely(ret != 0)) - return ret; - - ret = vmw_translate_guest_ptr(dev_priv, sw_context, - &cmd->q.guestResult, - &vmw_bo); - if (unlikely(ret != 0)) - return ret; - - vmw_dmabuf_unreference(&vmw_bo); - return 0; -} -static int vmw_cmd_wait_query(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - SVGA3dCmdHeader *header) -{ - struct vmw_dma_buffer *vmw_bo; - struct vmw_query_cmd { - SVGA3dCmdHeader header; - SVGA3dCmdWaitForQuery q; - } *cmd; - int ret; - - cmd = container_of(header, struct vmw_query_cmd, header); - ret = vmw_cmd_cid_check(dev_priv, sw_context, header); - if (unlikely(ret != 0)) - return ret; - - ret = vmw_translate_guest_ptr(dev_priv, sw_context, - &cmd->q.guestResult, - &vmw_bo); - if (unlikely(ret != 0)) - return ret; - - vmw_dmabuf_unreference(&vmw_bo); - return 0; -} - - -static int vmw_cmd_dma(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - SVGA3dCmdHeader *header) -{ - struct vmw_dma_buffer *vmw_bo = NULL; - struct ttm_buffer_object *bo; - struct vmw_surface *srf = NULL; - struct vmw_dma_cmd { - SVGA3dCmdHeader header; - SVGA3dCmdSurfaceDMA dma; - } *cmd; - int ret; - - cmd = container_of(header, struct vmw_dma_cmd, header); - ret = vmw_translate_guest_ptr(dev_priv, sw_context, - &cmd->dma.guest.ptr, - &vmw_bo); - if (unlikely(ret != 0)) - return ret; - - bo = &vmw_bo->base; ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile, cmd->dma.host.sid, &srf); if (ret) { @@ -455,8 +379,8 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = { VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw), VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check), - VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query), - VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query), + VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_cid_check), + VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok), VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, &vmw_cmd_blt_surf_screen_check) diff --git a/trunk/drivers/hid/Kconfig b/trunk/drivers/hid/Kconfig index 71d4c0703629..24d90ea246ce 100644 --- a/trunk/drivers/hid/Kconfig +++ b/trunk/drivers/hid/Kconfig @@ -55,12 +55,6 @@ source "drivers/hid/usbhid/Kconfig" menu "Special HID drivers" depends on HID -config HID_3M_PCT - tristate "3M PCT" - depends on USB_HID - ---help--- - Support for 3M PCT touch screens. - config HID_A4TECH tristate "A4 tech" if EMBEDDED depends on USB_HID @@ -189,23 +183,6 @@ config LOGIRUMBLEPAD2_FF Say Y here if you want to enable force feedback support for Logitech Rumblepad 2 devices. -config LOGIG940_FF - bool "Logitech Flight System G940 force feedback support" - depends on HID_LOGITECH - select INPUT_FF_MEMLESS - help - Say Y here if you want to enable force feedback support for Logitech - Flight System G940 devices. - -config HID_MAGICMOUSE - tristate "Apple MagicMouse multi-touch support" - depends on BT_HIDP - ---help--- - Support for the Apple Magic Mouse multi-touch. - - Say Y here if you want support for the multi-touch features of the - Apple Wireless "Magic" Mouse. - config HID_MICROSOFT tristate "Microsoft" if EMBEDDED depends on USB_HID @@ -213,12 +190,6 @@ config HID_MICROSOFT ---help--- Support for Microsoft devices that are not fully compliant with HID standard. -config HID_MOSART - tristate "MosArt" - depends on USB_HID - ---help--- - Support for MosArt dual-touch panels. - config HID_MONTEREY tristate "Monterey" if EMBEDDED depends on USB_HID @@ -227,17 +198,11 @@ config HID_MONTEREY Support for Monterey Genius KB29E. config HID_NTRIG - tristate "NTrig" - depends on USB_HID - ---help--- - Support for N-Trig touch screen. - -config HID_ORTEK - tristate "Ortek" if EMBEDDED + tristate "NTrig" if EMBEDDED depends on USB_HID default !EMBEDDED ---help--- - Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. + Support for N-Trig touch screen. config HID_PANTHERLORD tristate "Pantherlord support" if EMBEDDED @@ -262,12 +227,6 @@ config HID_PETALYNX ---help--- Support for Petalynx Maxter remote control. -config HID_QUANTA - tristate "Quanta Optical Touch" - depends on USB_HID - ---help--- - Support for Quanta Optical Touch dual-touch panels. - config HID_SAMSUNG tristate "Samsung" if EMBEDDED depends on USB_HID @@ -282,12 +241,6 @@ config HID_SONY ---help--- Support for Sony PS3 controller. -config HID_STANTUM - tristate "Stantum" - depends on USB_HID - ---help--- - Support for Stantum multitouch panel. - config HID_SUNPLUS tristate "Sunplus" if EMBEDDED depends on USB_HID @@ -352,8 +305,9 @@ config THRUSTMASTER_FF Rumble Force or Force Feedback Wheel. config HID_WACOM - tristate "Wacom Bluetooth devices support" + tristate "Wacom Bluetooth devices support" if EMBEDDED depends on BT_HIDP + default !EMBEDDED ---help--- Support for Wacom Graphire Bluetooth tablet. diff --git a/trunk/drivers/hid/Makefile b/trunk/drivers/hid/Makefile index 0b2618f092ca..0de2dff5542c 100644 --- a/trunk/drivers/hid/Makefile +++ b/trunk/drivers/hid/Makefile @@ -18,11 +18,7 @@ endif ifdef CONFIG_LOGIRUMBLEPAD2_FF hid-logitech-objs += hid-lg2ff.o endif -ifdef CONFIG_LOGIG940_FF - hid-logitech-objs += hid-lg3ff.o -endif -obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o @@ -35,19 +31,14 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KYE) += hid-kye.o obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o -obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o -obj-$(CONFIG_HID_MOSART) += hid-mosart.o obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o -obj-$(CONFIG_HID_ORTEK) += hid-ortek.o -obj-$(CONFIG_HID_QUANTA) += hid-quanta.o obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SONY) += hid-sony.o -obj-$(CONFIG_HID_STANTUM) += hid-stantum.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o diff --git a/trunk/drivers/hid/hid-3m-pct.c b/trunk/drivers/hid/hid-3m-pct.c deleted file mode 100644 index 2370aefc86b2..000000000000 --- a/trunk/drivers/hid/hid-3m-pct.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * HID driver for 3M PCT multitouch panels - * - * Copyright (c) 2009 Stephane Chatty - * - */ - -/* - * 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 -#include -#include -#include - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("3M PCT multitouch panels"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct mmm_finger { - __s32 x, y; - __u8 rank; - bool touch, valid; -}; - -struct mmm_data { - struct mmm_finger f[10]; - __u8 curid, num; - bool touch, valid; -}; - -static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_BUTTON: - return -1; - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - /* we do not want to map these: no input-oriented meaning */ - case 0x14: - case 0x23: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - case HID_DG_INRANGE: - case HID_DG_CONFIDENCE: - return -1; - case HID_DG_TIPSWITCH: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - } - /* let hid-input decide for the others */ - return 0; - - case 0xff000000: - /* we do not want to map these: no input-oriented meaning */ - return -1; - } - - return 0; -} - -static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole packet has been received and processed, - * so that it can decide what to send to the input layer. - */ -static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) -{ - struct mmm_finger *oldest = 0; - bool pressed = false, released = false; - int i; - - /* - * we need to iterate on all fingers to decide if we have a press - * or a release event in our touchscreen emulation. - */ - for (i = 0; i < 10; ++i) { - struct mmm_finger *f = &md->f[i]; - if (!f->valid) { - /* this finger is just placeholder data, ignore */ - } else if (f->touch) { - /* this finger is on the screen */ - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); - input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); - input_mt_sync(input); - /* - * touchscreen emulation: maintain the age rank - * of this finger, decide if we have a press - */ - if (f->rank == 0) { - f->rank = ++(md->num); - if (f->rank == 1) - pressed = true; - } - if (f->rank == 1) - oldest = f; - } else { - /* this finger took off the screen */ - /* touchscreen emulation: maintain age rank of others */ - int j; - - for (j = 0; j < 10; ++j) { - struct mmm_finger *g = &md->f[j]; - if (g->rank > f->rank) { - g->rank--; - if (g->rank == 1) - oldest = g; - } - } - f->rank = 0; - --(md->num); - if (md->num == 0) - released = true; - } - f->valid = 0; - } - - /* touchscreen emulation */ - if (oldest) { - if (pressed) - input_event(input, EV_KEY, BTN_TOUCH, 1); - input_event(input, EV_ABS, ABS_X, oldest->x); - input_event(input, EV_ABS, ABS_Y, oldest->y); - } else if (released) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - } -} - -/* - * this function is called upon all reports - * so that we can accumulate contact point information, - * and call input_mt_sync after each point. - */ -static int mmm_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct mmm_data *md = hid_get_drvdata(hid); - /* - * strangely, this function can be called before - * field->hidinput is initialized! - */ - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - switch (usage->hid) { - case HID_DG_TIPSWITCH: - md->touch = value; - break; - case HID_DG_CONFIDENCE: - md->valid = value; - break; - case HID_DG_CONTACTID: - if (md->valid) { - md->curid = value; - md->f[value].touch = md->touch; - md->f[value].valid = 1; - } - break; - case HID_GD_X: - if (md->valid) - md->f[md->curid].x = value; - break; - case HID_GD_Y: - if (md->valid) - md->f[md->curid].y = value; - break; - case HID_DG_CONTACTCOUNT: - mmm_filter_event(md, input); - break; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct mmm_data *md; - - md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); - if (!md) { - dev_err(&hdev->dev, "cannot allocate 3M data\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, md); - - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret) - kfree(md); - return ret; -} - -static void mmm_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id mmm_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, - { } -}; -MODULE_DEVICE_TABLE(hid, mmm_devices); - -static const struct hid_usage_id mmm_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver mmm_driver = { - .name = "3m-pct", - .id_table = mmm_devices, - .probe = mmm_probe, - .remove = mmm_remove, - .input_mapping = mmm_input_mapping, - .input_mapped = mmm_input_mapped, - .usage_table = mmm_grabbed_usages, - .event = mmm_event, -}; - -static int __init mmm_init(void) -{ - return hid_register_driver(&mmm_driver); -} - -static void __exit mmm_exit(void) -{ - hid_unregister_driver(&mmm_driver); -} - -module_init(mmm_init); -module_exit(mmm_exit); -MODULE_LICENSE("GPL"); - diff --git a/trunk/drivers/hid/hid-apple.c b/trunk/drivers/hid/hid-apple.c index 78286b184ace..5b4d66dc1a05 100644 --- a/trunk/drivers/hid/hid-apple.c +++ b/trunk/drivers/hid/hid-apple.c @@ -40,11 +40,6 @@ module_param(fnmode, uint, 0644); MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, " "[1] = fkeyslast, 2 = fkeysfirst)"); -static unsigned int iso_layout = 1; -module_param(iso_layout, uint, 0644); -MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. " - "(0 = disabled, [1] = enabled)"); - struct apple_sc { unsigned long quirks; unsigned int fn_on; @@ -204,13 +199,11 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } } - if (iso_layout) { - if (asc->quirks & APPLE_ISO_KEYBOARD) { - trans = apple_find_translation(apple_iso_keyboard, usage->code); - if (trans) { - input_event(input, usage->type, trans->to, value); - return 1; - } + if (asc->quirks & APPLE_ISO_KEYBOARD) { + trans = apple_find_translation(apple_iso_keyboard, usage->code); + if (trans) { + input_event(input, usage->type, trans->to, value); + return 1; } } diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index 368fbb0c4ca6..eabe5f87c6c1 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -4,7 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006-2010 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina */ /* @@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(hid_debug); * Register a new report for a device. */ -struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) +static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) { struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report *report; @@ -75,7 +75,6 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, return report; } -EXPORT_SYMBOL_GPL(hid_register_report); /* * Register a new field for this report. @@ -388,8 +387,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) __u32 data; unsigned n; - /* Local delimiter could have value 0, which allows size to be 0 */ - if (item->size == 0 && item->tag != HID_LOCAL_ITEM_TAG_DELIMITER) { + if (item->size == 0) { dbg_hid("item data expected for local item\n"); return -1; } @@ -1250,13 +1248,11 @@ EXPORT_SYMBOL_GPL(hid_disconnect); /* a list of devices for which there is a specialized driver on HID bus */ static const struct hid_device_id hid_blacklist[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, @@ -1328,7 +1324,6 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, @@ -1342,15 +1337,10 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, @@ -1553,9 +1543,8 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, @@ -1672,6 +1661,8 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) }, + { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, diff --git a/trunk/drivers/hid/hid-debug.c b/trunk/drivers/hid/hid-debug.c index cd4ece6fdfb9..6abd0369aedb 100644 --- a/trunk/drivers/hid/hid-debug.c +++ b/trunk/drivers/hid/hid-debug.c @@ -864,13 +864,13 @@ static const char **names[EV_MAX + 1] = { [EV_SND] = sounds, [EV_REP] = repeats, }; -static void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) -{ +void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) { + seq_printf(f, "%s.%s", events[type] ? events[type] : "?", names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); } -static void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) +void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) { int i, j, k; struct hid_report *report; diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index 72c05f90553c..010368e649ed 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -18,9 +18,6 @@ #ifndef HID_IDS_H_FILE #define HID_IDS_H_FILE -#define USB_VENDOR_ID_3M 0x0596 -#define USB_DEVICE_ID_3M1968 0x0500 - #define USB_VENDOR_ID_A4TECH 0x09da #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a @@ -59,7 +56,6 @@ #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 -#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 @@ -100,12 +96,9 @@ #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 -#define USB_VENDOR_ID_ASUS 0x0486 -#define USB_DEVICE_ID_ASUS_T91MT 0x0185 - -#define USB_VENDOR_ID_ASUSTEK 0x0b05 -#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 -#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b +#define USB_VENDOR_ID_ASUS 0x0b05 +#define USB_DEVICE_ID_ASUS_LCM 0x1726 +#define USB_DEVICE_ID_ASUS_LCM2 0x175b #define USB_VENDOR_ID_ATEN 0x0557 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 @@ -176,9 +169,6 @@ #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 -#define USB_VENDOR_ID_ETURBOTOUCH 0x22b9 -#define USB_DEVICE_ID_ETURBOTOUCH 0x0006 - #define USB_VENDOR_ID_ETT 0x0664 #define USB_DEVICE_ID_TC5UH 0x0309 @@ -313,7 +303,6 @@ #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 -#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287 #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 @@ -376,9 +365,6 @@ #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 -#define USB_VENDOR_ID_ORTEK 0x05a4 -#define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 - #define USB_VENDOR_ID_PANJIT 0x134c #define USB_VENDOR_ID_PANTHERLORD 0x0810 @@ -396,16 +382,9 @@ #define USB_VENDOR_ID_POWERCOM 0x0d9f #define USB_DEVICE_ID_POWERCOM_UPS 0x0002 -#define USB_VENDOR_ID_PRODIGE 0x05af -#define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 - #define USB_VENDOR_ID_SAITEK 0x06a3 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 -#define USB_VENDOR_ID_QUANTA 0x0408 -#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 -#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 - #define USB_VENDOR_ID_SAMSUNG 0x0419 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 @@ -417,19 +396,17 @@ #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 -#define USB_VENDOR_ID_STANTUM 0x1f87 -#define USB_DEVICE_ID_MTP 0x0002 - #define USB_VENDOR_ID_SUN 0x0430 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab #define USB_VENDOR_ID_SUNPLUS 0x04fc #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 -#define USB_VENDOR_ID_THRUSTMASTER 0x044f +#define USB_VENDOR_ID_TENX 0x1130 +#define USB_DEVICE_ID_TENX_IBUDDY1 0x0001 +#define USB_DEVICE_ID_TENX_IBUDDY2 0x0002 -#define USB_VENDOR_ID_TOUCHPACK 0x1bfd -#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 +#define USB_VENDOR_ID_THRUSTMASTER 0x044f #define USB_VENDOR_ID_TOPMAX 0x0663 #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 diff --git a/trunk/drivers/hid/hid-input.c b/trunk/drivers/hid/hid-input.c index 79d9edd0bdfa..5862b0f3b55d 100644 --- a/trunk/drivers/hid/hid-input.c +++ b/trunk/drivers/hid/hid-input.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2000-2001 Vojtech Pavlik - * Copyright (c) 2006-2010 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina * * HID to Linux Input mapping */ @@ -193,17 +193,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel break; case HID_UP_BUTTON: - code = ((usage->hid - 1) & HID_USAGE); + code = ((usage->hid - 1) & 0xf); switch (field->application) { case HID_GD_MOUSE: case HID_GD_POINTER: code += 0x110; break; - case HID_GD_JOYSTICK: - if (code <= 0xf) - code += BTN_JOYSTICK; - else - code += BTN_TRIGGER_HAPPY; - break; + case HID_GD_JOYSTICK: code += 0x120; break; case HID_GD_GAMEPAD: code += 0x130; break; default: switch (field->physical) { @@ -405,7 +400,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x192: map_key_clear(KEY_CALC); break; case 0x194: map_key_clear(KEY_FILE); break; case 0x196: map_key_clear(KEY_WWW); break; - case 0x199: map_key_clear(KEY_CHAT); break; case 0x19c: map_key_clear(KEY_LOGOFF); break; case 0x19e: map_key_clear(KEY_COFFEE); break; case 0x1a6: map_key_clear(KEY_HELP); break; diff --git a/trunk/drivers/hid/hid-lg.c b/trunk/drivers/hid/hid-lg.c index 3677c9037a11..9fcd3d017ab3 100644 --- a/trunk/drivers/hid/hid-lg.c +++ b/trunk/drivers/hid/hid-lg.c @@ -34,7 +34,6 @@ #define LG_FF 0x200 #define LG_FF2 0x400 #define LG_RDESC_REL_ABS 0x800 -#define LG_FF3 0x1000 /* * Certain Logitech keyboards send in report #3 keys which are far @@ -267,7 +266,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_free; } - if (quirks & (LG_FF | LG_FF2 | LG_FF3)) + if (quirks & (LG_FF | LG_FF2)) connect_mask &= ~HID_CONNECT_FF; ret = hid_hw_start(hdev, connect_mask); @@ -280,8 +279,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) lgff_init(hdev); if (quirks & LG_FF2) lg2ff_init(hdev); - if (quirks & LG_FF3) - lg3ff_init(hdev); return 0; err_free: @@ -334,8 +331,6 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), .driver_data = LG_FF2 }, - { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940), - .driver_data = LG_FF3 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR), .driver_data = LG_RDESC_REL_ABS }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER), diff --git a/trunk/drivers/hid/hid-lg.h b/trunk/drivers/hid/hid-lg.h index ce2ac8672624..bf31592eaf79 100644 --- a/trunk/drivers/hid/hid-lg.h +++ b/trunk/drivers/hid/hid-lg.h @@ -13,10 +13,4 @@ int lg2ff_init(struct hid_device *hdev); static inline int lg2ff_init(struct hid_device *hdev) { return -1; } #endif -#ifdef CONFIG_LOGIG940_FF -int lg3ff_init(struct hid_device *hdev); -#else -static inline int lg3ff_init(struct hid_device *hdev) { return -1; } -#endif - #endif diff --git a/trunk/drivers/hid/hid-lg3ff.c b/trunk/drivers/hid/hid-lg3ff.c deleted file mode 100644 index 4002832ee4af..000000000000 --- a/trunk/drivers/hid/hid-lg3ff.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Force feedback support for Logitech Flight System G940 - * - * Copyright (c) 2009 Gary Stein - */ - -/* - * 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 -#include -#include - -#include "usbhid/usbhid.h" -#include "hid-lg.h" - -/* - * G940 Theory of Operation (from experimentation) - * - * There are 63 fields (only 3 of them currently used) - * 0 - seems to be command field - * 1 - 30 deal with the x axis - * 31 -60 deal with the y axis - * - * Field 1 is x axis constant force - * Field 31 is y axis constant force - * - * other interesting fields 1,2,3,4 on x axis - * (same for 31,32,33,34 on y axis) - * - * 0 0 127 127 makes the joystick autocenter hard - * - * 127 0 127 127 makes the joystick loose on the right, - * but stops all movemnt left - * - * -127 0 -127 -127 makes the joystick loose on the left, - * but stops all movement right - * - * 0 0 -127 -127 makes the joystick rattle very hard - * - * I'm sure these are effects that I don't know enough about them - */ - -struct lg3ff_device { - struct hid_report *report; -}; - -static int hid_lg3ff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int x, y; - -/* - * Maxusage should always be 63 (maximum fields) - * likely a better way to ensure this data is clean - */ - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); - - switch (effect->type) { - case FF_CONSTANT: -/* - * Already clamped in ff_memless - * 0 is center (different then other logitech) - */ - x = effect->u.ramp.start_level; - y = effect->u.ramp.end_level; - - /* send command byte */ - report->field[0]->value[0] = 0x51; - -/* - * Sign backwards from other Force3d pro - * which get recast here in two's complement 8 bits - */ - report->field[0]->value[1] = (unsigned char)(-x); - report->field[0]->value[31] = (unsigned char)(-y); - - usbhid_submit_report(hid, report, USB_DIR_OUT); - break; - } - return 0; -} -static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude) -{ - struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - -/* - * Auto Centering probed from device - * NOTE: deadman's switch on G940 must be covered - * for effects to work - */ - report->field[0]->value[0] = 0x51; - report->field[0]->value[1] = 0x00; - report->field[0]->value[2] = 0x00; - report->field[0]->value[3] = 0x7F; - report->field[0]->value[4] = 0x7F; - report->field[0]->value[31] = 0x00; - report->field[0]->value[32] = 0x00; - report->field[0]->value[33] = 0x7F; - report->field[0]->value[34] = 0x7F; - - usbhid_submit_report(hid, report, USB_DIR_OUT); -} - - -static const signed short ff3_joystick_ac[] = { - FF_CONSTANT, - FF_AUTOCENTER, - -1 -}; - -int lg3ff_init(struct hid_device *hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; - const signed short *ff_bits = ff3_joystick_ac; - int error; - int i; - - /* Find the report to use */ - if (list_empty(report_list)) { - err_hid("No output report found"); - return -1; - } - - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - err_hid("NULL output report"); - return -1; - } - - field = report->field[0]; - if (!field) { - err_hid("NULL field"); - return -1; - } - - /* Assume single fixed device G940 */ - for (i = 0; ff_bits[i] >= 0; i++) - set_bit(ff_bits[i], dev->ffbit); - - error = input_ff_create_memless(dev, NULL, hid_lg3ff_play); - if (error) - return error; - - if (test_bit(FF_AUTOCENTER, dev->ffbit)) - dev->ff->set_autocenter = hid_lg3ff_set_autocenter; - - dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by " - "Gary Stein \n"); - return 0; -} - diff --git a/trunk/drivers/hid/hid-lgff.c b/trunk/drivers/hid/hid-lgff.c index 61142b76a9b1..987abebe0829 100644 --- a/trunk/drivers/hid/hid-lgff.c +++ b/trunk/drivers/hid/hid-lgff.c @@ -67,7 +67,6 @@ static const struct dev_type devices[] = { { 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc283, ff_joystick }, { 0x046d, 0xc286, ff_joystick_ac }, - { 0x046d, 0xc287, ff_joystick_ac }, { 0x046d, 0xc293, ff_joystick }, { 0x046d, 0xc294, ff_wheel }, { 0x046d, 0xc295, ff_joystick }, diff --git a/trunk/drivers/hid/hid-magicmouse.c b/trunk/drivers/hid/hid-magicmouse.c deleted file mode 100644 index 4a3a94f2b10c..000000000000 --- a/trunk/drivers/hid/hid-magicmouse.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Apple "Magic" Wireless Mouse driver - * - * Copyright (c) 2010 Michael Poole - */ - -/* - * 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 -#include -#include -#include - -#include "hid-ids.h" - -static bool emulate_3button = true; -module_param(emulate_3button, bool, 0644); -MODULE_PARM_DESC(emulate_3button, "Emulate a middle button"); - -static int middle_button_start = -350; -static int middle_button_stop = +350; - -static bool emulate_scroll_wheel = true; -module_param(emulate_scroll_wheel, bool, 0644); -MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); - -static bool report_touches = true; -module_param(report_touches, bool, 0644); -MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); - -static bool report_undeciphered; -module_param(report_undeciphered, bool, 0644); -MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); - -#define TOUCH_REPORT_ID 0x29 -/* These definitions are not precise, but they're close enough. (Bits - * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem - * to be some kind of bit mask -- 0x20 may be a near-field reading, - * and 0x40 is actual contact, and 0x10 may be a start/stop or change - * indication.) - */ -#define TOUCH_STATE_MASK 0xf0 -#define TOUCH_STATE_NONE 0x00 -#define TOUCH_STATE_START 0x30 -#define TOUCH_STATE_DRAG 0x40 - -/** - * struct magicmouse_sc - Tracks Magic Mouse-specific data. - * @input: Input device through which we report events. - * @quirks: Currently unused. - * @last_timestamp: Timestamp from most recent (18-bit) touch report - * (units of milliseconds over short windows, but seems to - * increase faster when there are no touches). - * @delta_time: 18-bit difference between the two most recent touch - * reports from the mouse. - * @ntouches: Number of touches in most recent touch report. - * @scroll_accel: Number of consecutive scroll motions. - * @scroll_jiffies: Time of last scroll motion. - * @touches: Most recent data for a touch, indexed by tracking ID. - * @tracking_ids: Mapping of current touch input data to @touches. - */ -struct magicmouse_sc { - struct input_dev *input; - unsigned long quirks; - - int last_timestamp; - int delta_time; - int ntouches; - int scroll_accel; - unsigned long scroll_jiffies; - - struct { - short x; - short y; - short scroll_y; - u8 size; - } touches[16]; - int tracking_ids[16]; -}; - -static int magicmouse_firm_touch(struct magicmouse_sc *msc) -{ - int touch = -1; - int ii; - - /* If there is only one "firm" touch, set touch to its - * tracking ID. - */ - for (ii = 0; ii < msc->ntouches; ii++) { - int idx = msc->tracking_ids[ii]; - if (msc->touches[idx].size < 8) { - /* Ignore this touch. */ - } else if (touch >= 0) { - touch = -1; - break; - } else { - touch = idx; - } - } - - return touch; -} - -static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) -{ - int last_state = test_bit(BTN_LEFT, msc->input->key) << 0 | - test_bit(BTN_RIGHT, msc->input->key) << 1 | - test_bit(BTN_MIDDLE, msc->input->key) << 2; - - if (emulate_3button) { - int id; - - /* If some button was pressed before, keep it held - * down. Otherwise, if there's exactly one firm - * touch, use that to override the mouse's guess. - */ - if (state == 0) { - /* The button was released. */ - } else if (last_state != 0) { - state = last_state; - } else if ((id = magicmouse_firm_touch(msc)) >= 0) { - int x = msc->touches[id].x; - if (x < middle_button_start) - state = 1; - else if (x > middle_button_stop) - state = 2; - else - state = 4; - } /* else: we keep the mouse's guess */ - - input_report_key(msc->input, BTN_MIDDLE, state & 4); - } - - input_report_key(msc->input, BTN_LEFT, state & 1); - input_report_key(msc->input, BTN_RIGHT, state & 2); - - if (state != last_state) - msc->scroll_accel = 0; -} - -static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) -{ - struct input_dev *input = msc->input; - __s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24; - int misc = tdata[5] | tdata[6] << 8; - int id = (misc >> 6) & 15; - int x = x_y << 12 >> 20; - int y = -(x_y >> 20); - - /* Store tracking ID and other fields. */ - msc->tracking_ids[raw_id] = id; - msc->touches[id].x = x; - msc->touches[id].y = y; - msc->touches[id].size = misc & 63; - - /* If requested, emulate a scroll wheel by detecting small - * vertical touch motions along the middle of the mouse. - */ - if (emulate_scroll_wheel && - middle_button_start < x && x < middle_button_stop) { - static const int accel_profile[] = { - 256, 228, 192, 160, 128, 96, 64, 32, - }; - unsigned long now = jiffies; - int step = msc->touches[id].scroll_y - y; - - /* Reset acceleration after half a second. */ - if (time_after(now, msc->scroll_jiffies + HZ / 2)) - msc->scroll_accel = 0; - - /* Calculate and apply the scroll motion. */ - switch (tdata[7] & TOUCH_STATE_MASK) { - case TOUCH_STATE_START: - msc->touches[id].scroll_y = y; - msc->scroll_accel = min_t(int, msc->scroll_accel + 1, - ARRAY_SIZE(accel_profile) - 1); - break; - case TOUCH_STATE_DRAG: - step = step / accel_profile[msc->scroll_accel]; - if (step != 0) { - msc->touches[id].scroll_y = y; - msc->scroll_jiffies = now; - input_report_rel(input, REL_WHEEL, step); - } - break; - } - } - - /* Generate the input events for this touch. */ - if (report_touches) { - int orientation = (misc >> 10) - 32; - - input_report_abs(input, ABS_MT_TRACKING_ID, id); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); - input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); - input_report_abs(input, ABS_MT_ORIENTATION, orientation); - input_report_abs(input, ABS_MT_POSITION_X, x); - input_report_abs(input, ABS_MT_POSITION_Y, y); - - if (report_undeciphered) - input_event(input, EV_MSC, MSC_RAW, tdata[7]); - - input_mt_sync(input); - } -} - -static int magicmouse_raw_event(struct hid_device *hdev, - struct hid_report *report, u8 *data, int size) -{ - struct magicmouse_sc *msc = hid_get_drvdata(hdev); - struct input_dev *input = msc->input; - int x, y, ts, ii, clicks; - - switch (data[0]) { - case 0x10: - if (size != 6) - return 0; - x = (__s16)(data[2] | data[3] << 8); - y = (__s16)(data[4] | data[5] << 8); - clicks = data[1]; - break; - case TOUCH_REPORT_ID: - /* Expect six bytes of prefix, and N*8 bytes of touch data. */ - if (size < 6 || ((size - 6) % 8) != 0) - return 0; - ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; - msc->delta_time = (ts - msc->last_timestamp) & 0x3ffff; - msc->last_timestamp = ts; - msc->ntouches = (size - 6) / 8; - for (ii = 0; ii < msc->ntouches; ii++) - magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); - /* When emulating three-button mode, it is important - * to have the current touch information before - * generating a click event. - */ - x = (signed char)data[1]; - y = (signed char)data[2]; - clicks = data[3]; - break; - case 0x20: /* Theoretically battery status (0-100), but I have - * never seen it -- maybe it is only upon request. - */ - case 0x60: /* Unknown, maybe laser on/off. */ - case 0x61: /* Laser reflection status change. - * data[1]: 0 = spotted, 1 = lost - */ - default: - return 0; - } - - magicmouse_emit_buttons(msc, clicks & 3); - input_report_rel(input, REL_X, x); - input_report_rel(input, REL_Y, y); - input_sync(input); - return 1; -} - -static int magicmouse_input_open(struct input_dev *dev) -{ - struct hid_device *hid = input_get_drvdata(dev); - - return hid->ll_driver->open(hid); -} - -static void magicmouse_input_close(struct input_dev *dev) -{ - struct hid_device *hid = input_get_drvdata(dev); - - hid->ll_driver->close(hid); -} - -static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) -{ - input_set_drvdata(input, hdev); - input->event = hdev->ll_driver->hidinput_input_event; - input->open = magicmouse_input_open; - input->close = magicmouse_input_close; - - input->name = hdev->name; - input->phys = hdev->phys; - input->uniq = hdev->uniq; - input->id.bustype = hdev->bus; - input->id.vendor = hdev->vendor; - input->id.product = hdev->product; - input->id.version = hdev->version; - input->dev.parent = hdev->dev.parent; - - __set_bit(EV_KEY, input->evbit); - __set_bit(BTN_LEFT, input->keybit); - __set_bit(BTN_RIGHT, input->keybit); - if (emulate_3button) - __set_bit(BTN_MIDDLE, input->keybit); - __set_bit(BTN_TOOL_FINGER, input->keybit); - - __set_bit(EV_REL, input->evbit); - __set_bit(REL_X, input->relbit); - __set_bit(REL_Y, input->relbit); - if (emulate_scroll_wheel) - __set_bit(REL_WHEEL, input->relbit); - - if (report_touches) { - __set_bit(EV_ABS, input->evbit); - - input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); - input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); - input_set_abs_params(input, ABS_MT_POSITION_X, -1100, 1358, - 4, 0); - /* Note: Touch Y position from the device is inverted relative - * to how pointer motion is reported (and relative to how USB - * HID recommends the coordinates work). This driver keeps - * the origin at the same position, and just uses the additive - * inverse of the reported Y. - */ - input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, 2047, - 4, 0); - } - - if (report_undeciphered) { - __set_bit(EV_MSC, input->evbit); - __set_bit(MSC_RAW, input->mscbit); - } -} - -static int magicmouse_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - __u8 feature_1[] = { 0xd7, 0x01 }; - __u8 feature_2[] = { 0xf8, 0x01, 0x32 }; - struct input_dev *input; - struct magicmouse_sc *msc; - struct hid_report *report; - int ret; - - msc = kzalloc(sizeof(*msc), GFP_KERNEL); - if (msc == NULL) { - dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n"); - return -ENOMEM; - } - - msc->quirks = id->driver_data; - hid_set_drvdata(hdev, msc); - - ret = hid_parse(hdev); - if (ret) { - dev_err(&hdev->dev, "magicmouse hid parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - if (ret) { - dev_err(&hdev->dev, "magicmouse hw start failed\n"); - goto err_free; - } - - report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID); - if (!report) { - dev_err(&hdev->dev, "unable to register touch report\n"); - ret = -ENOMEM; - goto err_stop_hw; - } - report->size = 6; - - ret = hdev->hid_output_raw_report(hdev, feature_1, sizeof(feature_1), - HID_FEATURE_REPORT); - if (ret != sizeof(feature_1)) { - dev_err(&hdev->dev, "unable to request touch data (1:%d)\n", - ret); - goto err_stop_hw; - } - ret = hdev->hid_output_raw_report(hdev, feature_2, - sizeof(feature_2), HID_FEATURE_REPORT); - if (ret != sizeof(feature_2)) { - dev_err(&hdev->dev, "unable to request touch data (2:%d)\n", - ret); - goto err_stop_hw; - } - - input = input_allocate_device(); - if (!input) { - dev_err(&hdev->dev, "can't alloc input device\n"); - ret = -ENOMEM; - goto err_stop_hw; - } - magicmouse_setup_input(input, hdev); - - ret = input_register_device(input); - if (ret) { - dev_err(&hdev->dev, "input device registration failed\n"); - goto err_input; - } - msc->input = input; - - return 0; -err_input: - input_free_device(input); -err_stop_hw: - hid_hw_stop(hdev); -err_free: - kfree(msc); - return ret; -} - -static void magicmouse_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); -} - -static const struct hid_device_id magic_mice[] = { - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE), - .driver_data = 0 }, - { } -}; -MODULE_DEVICE_TABLE(hid, magic_mice); - -static struct hid_driver magicmouse_driver = { - .name = "magicmouse", - .id_table = magic_mice, - .probe = magicmouse_probe, - .remove = magicmouse_remove, - .raw_event = magicmouse_raw_event, -}; - -static int __init magicmouse_init(void) -{ - int ret; - - ret = hid_register_driver(&magicmouse_driver); - if (ret) - printk(KERN_ERR "can't register magicmouse driver\n"); - - return ret; -} - -static void __exit magicmouse_exit(void) -{ - hid_unregister_driver(&magicmouse_driver); -} - -module_init(magicmouse_init); -module_exit(magicmouse_exit); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/hid/hid-mosart.c b/trunk/drivers/hid/hid-mosart.c deleted file mode 100644 index c8718168fe42..000000000000 --- a/trunk/drivers/hid/hid-mosart.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * HID driver for the multitouch panel on the ASUS EeePC T91MT - * - * Copyright (c) 2009-2010 Stephane Chatty - * Copyright (c) 2010 Teemu Tuominen - * - */ - -/* - * 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 -#include -#include -#include -#include "usbhid/usbhid.h" - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("MosArt dual-touch panel"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct mosart_data { - __u16 x, y; - __u8 id; - bool valid; /* valid finger data, or just placeholder? */ - bool first; /* is this the first finger in this frame? */ - bool activity_now; /* at least one active finger in this frame? */ - bool activity; /* at least one active finger previously? */ -}; - -static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - case HID_DG_TIPPRESSURE: - case HID_DG_WIDTH: - case HID_DG_HEIGHT: - return -1; - case HID_DG_INRANGE: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - - } - return 0; - - case 0xff000000: - /* ignore HID features */ - return -1; - } - - return 0; -} - -static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole finger has been parsed, - * so that it can decide what to send to the input layer. - */ -static void mosart_filter_event(struct mosart_data *td, struct input_dev *input) -{ - td->first = !td->first; /* touchscreen emulation */ - - if (!td->valid) { - /* - * touchscreen emulation: if no finger in this frame is valid - * and there previously was finger activity, this is a release - */ - if (!td->first && !td->activity_now && td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - td->activity = false; - } - return; - } - - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); - - input_mt_sync(input); - td->valid = false; - - /* touchscreen emulation: if first active finger in this frame... */ - if (!td->activity_now) { - /* if there was no previous activity, emit touch event */ - if (!td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - td->activity = true; - } - td->activity_now = true; - /* and in any case this is our preferred finger */ - input_event(input, EV_ABS, ABS_X, td->x); - input_event(input, EV_ABS, ABS_Y, td->y); - } -} - - -static int mosart_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct mosart_data *td = hid_get_drvdata(hid); - - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - switch (usage->hid) { - case HID_DG_INRANGE: - td->valid = !!value; - break; - case HID_GD_X: - td->x = value; - break; - case HID_GD_Y: - td->y = value; - mosart_filter_event(td, input); - break; - case HID_DG_CONTACTID: - td->id = value; - break; - case HID_DG_CONTACTCOUNT: - /* touch emulation: this is the last field in a frame */ - td->first = false; - td->activity_now = false; - break; - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - /* avoid interference from generic hidinput handling */ - break; - - default: - /* fallback to the generic hidinput handling */ - return 0; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct mosart_data *td; - - - td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL); - if (!td) { - dev_err(&hdev->dev, "cannot allocate MosArt data\n"); - return -ENOMEM; - } - td->valid = false; - td->activity = false; - td->activity_now = false; - td->first = false; - hid_set_drvdata(hdev, td); - - /* currently, it's better to have one evdev device only */ -#if 0 - hdev->quirks |= HID_QUIRK_MULTI_INPUT; -#endif - - ret = hid_parse(hdev); - if (ret == 0) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret == 0) { - struct hid_report_enum *re = hdev->report_enum - + HID_FEATURE_REPORT; - struct hid_report *r = re->report_id_hash[7]; - - r->field[0]->value[0] = 0x02; - usbhid_submit_report(hdev, r, USB_DIR_OUT); - } else - kfree(td); - - return ret; -} - -static void mosart_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id mosart_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, - { } -}; -MODULE_DEVICE_TABLE(hid, mosart_devices); - -static const struct hid_usage_id mosart_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver mosart_driver = { - .name = "mosart", - .id_table = mosart_devices, - .probe = mosart_probe, - .remove = mosart_remove, - .input_mapping = mosart_input_mapping, - .input_mapped = mosart_input_mapped, - .usage_table = mosart_grabbed_usages, - .event = mosart_event, -}; - -static int __init mosart_init(void) -{ - return hid_register_driver(&mosart_driver); -} - -static void __exit mosart_exit(void) -{ - hid_unregister_driver(&mosart_driver); -} - -module_init(mosart_init); -module_exit(mosart_exit); - diff --git a/trunk/drivers/hid/hid-ntrig.c b/trunk/drivers/hid/hid-ntrig.c index 3234c729a895..49ce69d7bba7 100644 --- a/trunk/drivers/hid/hid-ntrig.c +++ b/trunk/drivers/hid/hid-ntrig.c @@ -25,16 +25,11 @@ EV_KEY, (c)) struct ntrig_data { - /* Incoming raw values for a single contact */ - __u16 x, y, w, h; - __u16 id; - __u8 confidence; - - bool reading_mt; - __u8 first_contact_confidence; - - __u8 mt_footer[4]; - __u8 mt_foot_count; + __s32 x, y, id, w, h; + char reading_a_point, found_contact_id; + char pen_active; + char finger_active; + char inverted; }; /* @@ -47,11 +42,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - /* No special mappings needed for the pen and single touch */ - if (field->physical) - return 0; - switch (usage->hid & HID_USAGE_PAGE) { + case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: @@ -74,12 +66,18 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_UP_DIGITIZER: switch (usage->hid) { /* we do not want to map these for now */ - case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */ + case HID_DG_CONTACTID: /* value is useless */ case HID_DG_INPUTMODE: case HID_DG_DEVICEINDEX: + case HID_DG_CONTACTCOUNT: case HID_DG_CONTACTMAX: return -1; + /* original mapping by Rafi Rubin */ + case HID_DG_CONFIDENCE: + nt_map_key_clear(BTN_TOOL_DOUBLETAP); + return 1; + /* width/height mapped on TouchMajor/TouchMinor/Orientation */ case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, @@ -106,10 +104,6 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - /* No special mappings needed for the pen and single touch */ - if (field->physical) - return 0; - if (usage->type == EV_KEY || usage->type == EV_REL || usage->type == EV_ABS) clear_bit(usage->code, *bit); @@ -129,30 +123,31 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, struct input_dev *input = field->hidinput->input; struct ntrig_data *nd = hid_get_drvdata(hid); - /* No special handling needed for the pen */ - if (field->application == HID_DG_PEN) - return 0; - if (hid->claimed & HID_CLAIMED_INPUT) { switch (usage->hid) { - case 0xff000001: - /* Tag indicating the start of a multitouch group */ - nd->reading_mt = 1; - nd->first_contact_confidence = 0; - break; - case HID_DG_CONFIDENCE: - nd->confidence = value; - break; + + case HID_DG_INRANGE: + if (field->application & 0x3) + nd->pen_active = (value != 0); + else + nd->finger_active = (value != 0); + return 0; + + case HID_DG_INVERT: + nd->inverted = value; + return 0; + case HID_GD_X: nd->x = value; - /* Clear the contact footer */ - nd->mt_foot_count = 0; + nd->reading_a_point = 1; break; case HID_GD_Y: nd->y = value; break; case HID_DG_CONTACTID: nd->id = value; + /* we receive this only when in multitouch mode */ + nd->found_contact_id = 1; break; case HID_DG_WIDTH: nd->w = value; @@ -164,13 +159,35 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, * report received in a finger event. We want * to emit a normal (X, Y) position */ - if (!nd->reading_mt) { - input_report_key(input, BTN_TOOL_DOUBLETAP, - (nd->confidence != 0)); + if (!nd->found_contact_id) { + if (nd->pen_active && nd->finger_active) { + input_report_key(input, BTN_TOOL_DOUBLETAP, 0); + input_report_key(input, BTN_TOOL_DOUBLETAP, 1); + } input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } break; + case HID_DG_TIPPRESSURE: + /* + * when in single touch mode, this is the last + * report received in a pen event. We want + * to emit a normal (X, Y) position + */ + if (! nd->found_contact_id) { + if (nd->pen_active && nd->finger_active) { + input_report_key(input, + nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN + , 0); + input_report_key(input, + nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN + , 1); + } + input_event(input, EV_ABS, ABS_X, nd->x); + input_event(input, EV_ABS, ABS_Y, nd->y); + input_event(input, EV_ABS, ABS_PRESSURE, value); + } + break; case 0xff000002: /* * we receive this when the device is in multitouch @@ -178,34 +195,10 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, * this usage tells if the contact point is real * or a placeholder */ - - /* Shouldn't get more than 4 footer packets, so skip */ - if (nd->mt_foot_count >= 4) + if (!nd->reading_a_point || value != 1) break; - - nd->mt_footer[nd->mt_foot_count++] = value; - - /* if the footer isn't complete break */ - if (nd->mt_foot_count != 4) - break; - - /* Pen activity signal, trigger end of touch. */ - if (nd->mt_footer[2]) { - nd->confidence = 0; - break; - } - - /* If the contact was invalid */ - if (!(nd->confidence && nd->mt_footer[0]) - || nd->w <= 250 - || nd->h <= 190) { - nd->confidence = 0; - break; - } - /* emit a normal (X, Y) for the first point only */ if (nd->id == 0) { - nd->first_contact_confidence = nd->confidence; input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } @@ -227,39 +220,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, ABS_MT_TOUCH_MINOR, nd->w); } input_mt_sync(field->hidinput->input); - break; - - case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ - if (!nd->reading_mt) - break; - - nd->reading_mt = 0; - - if (nd->first_contact_confidence) { - switch (value) { - case 0: /* for single touch devices */ - case 1: - input_report_key(input, - BTN_TOOL_DOUBLETAP, 1); - break; - case 2: - input_report_key(input, - BTN_TOOL_TRIPLETAP, 1); - break; - case 3: - default: - input_report_key(input, - BTN_TOOL_QUADTAP, 1); - } - input_report_key(input, BTN_TOUCH, 1); - } else { - input_report_key(input, - BTN_TOOL_DOUBLETAP, 0); - input_report_key(input, - BTN_TOOL_TRIPLETAP, 0); - input_report_key(input, - BTN_TOOL_QUADTAP, 0); - } + nd->reading_a_point = 0; + nd->found_contact_id = 0; break; default: @@ -269,8 +231,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, } /* we have handled the hidinput part, now remains hiddev */ - if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); + if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) + hid->hiddev_hid_event(hid, field, usage, value); return 1; } @@ -279,67 +241,23 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; struct ntrig_data *nd; - struct hid_input *hidinput; - struct input_dev *input; - - if (id->driver_data) - hdev->quirks |= HID_QUIRK_MULTI_INPUT; nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); if (!nd) { dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); return -ENOMEM; } - - nd->reading_mt = 0; + nd->reading_a_point = 0; + nd->found_contact_id = 0; hid_set_drvdata(hdev, nd); ret = hid_parse(hdev); - if (ret) { - dev_err(&hdev->dev, "parse failed\n"); - goto err_free; - } - - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); - if (ret) { - dev_err(&hdev->dev, "hw start failed\n"); - goto err_free; - } + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) + kfree (nd); - list_for_each_entry(hidinput, &hdev->inputs, list) { - input = hidinput->input; - switch (hidinput->report->field[0]->application) { - case HID_DG_PEN: - input->name = "N-Trig Pen"; - break; - case HID_DG_TOUCHSCREEN: - __clear_bit(BTN_TOOL_PEN, input->keybit); - /* - * A little something special to enable - * two and three finger taps. - */ - __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); - __set_bit(BTN_TOOL_QUADTAP, input->keybit); - /* - * The physical touchscreen (single touch) - * input has a value for physical, whereas - * the multitouch only has logical input - * fields. - */ - input->name = - (hidinput->report->field[0] - ->physical) ? - "N-Trig Touchscreen" : - "N-Trig MultiTouch"; - break; - } - } - - return 0; -err_free: - kfree(nd); return ret; } @@ -358,7 +276,7 @@ MODULE_DEVICE_TABLE(hid, ntrig_devices); static const struct hid_usage_id ntrig_grabbed_usages[] = { { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 } + { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} }; static struct hid_driver ntrig_driver = { diff --git a/trunk/drivers/hid/hid-ortek.c b/trunk/drivers/hid/hid-ortek.c deleted file mode 100644 index aa9a960f73a4..000000000000 --- a/trunk/drivers/hid/hid-ortek.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad). - * Fixes LogicalMaximum error in USB report description, see - * http://bugzilla.kernel.org/show_bug.cgi?id=14787 - * - * Copyright (c) 2010 Johnathon Harris - */ - -/* - * 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 -#include -#include - -#include "hid-ids.h" - -static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int rsize) -{ - if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { - dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " - "report descriptor.\n"); - rdesc[55] = 0x92; - } -} - -static const struct hid_device_id ortek_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { } -}; -MODULE_DEVICE_TABLE(hid, ortek_devices); - -static struct hid_driver ortek_driver = { - .name = "ortek", - .id_table = ortek_devices, - .report_fixup = ortek_report_fixup -}; - -static int __init ortek_init(void) -{ - return hid_register_driver(&ortek_driver); -} - -static void __exit ortek_exit(void) -{ - hid_unregister_driver(&ortek_driver); -} - -module_init(ortek_init); -module_exit(ortek_exit); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/hid/hid-quanta.c b/trunk/drivers/hid/hid-quanta.c deleted file mode 100644 index 01dd51c4986c..000000000000 --- a/trunk/drivers/hid/hid-quanta.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * HID driver for Quanta Optical Touch dual-touch panels - * - * Copyright (c) 2009-2010 Stephane Chatty - * - */ - -/* - * 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 -#include -#include - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("Quanta dual-touch panel"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct quanta_data { - __u16 x, y; - __u8 id; - bool valid; /* valid finger data, or just placeholder? */ - bool first; /* is this the first finger in this frame? */ - bool activity_now; /* at least one active finger in this frame? */ - bool activity; /* at least one active finger previously? */ -}; - -static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - case HID_DG_TIPPRESSURE: - case HID_DG_WIDTH: - case HID_DG_HEIGHT: - return -1; - case HID_DG_INRANGE: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - } - return 0; - - case 0xff000000: - /* ignore vendor-specific features */ - return -1; - } - - return 0; -} - -static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole finger has been parsed, - * so that it can decide what to send to the input layer. - */ -static void quanta_filter_event(struct quanta_data *td, struct input_dev *input) -{ - - td->first = !td->first; /* touchscreen emulation */ - - if (!td->valid) { - /* - * touchscreen emulation: if no finger in this frame is valid - * and there previously was finger activity, this is a release - */ - if (!td->first && !td->activity_now && td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - td->activity = false; - } - return; - } - - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); - - input_mt_sync(input); - td->valid = false; - - /* touchscreen emulation: if first active finger in this frame... */ - if (!td->activity_now) { - /* if there was no previous activity, emit touch event */ - if (!td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - td->activity = true; - } - td->activity_now = true; - /* and in any case this is our preferred finger */ - input_event(input, EV_ABS, ABS_X, td->x); - input_event(input, EV_ABS, ABS_Y, td->y); - } -} - - -static int quanta_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct quanta_data *td = hid_get_drvdata(hid); - - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - - switch (usage->hid) { - case HID_DG_INRANGE: - td->valid = !!value; - break; - case HID_GD_X: - td->x = value; - break; - case HID_GD_Y: - td->y = value; - quanta_filter_event(td, input); - break; - case HID_DG_CONTACTID: - td->id = value; - break; - case HID_DG_CONTACTCOUNT: - /* touch emulation: this is the last field in a frame */ - td->first = false; - td->activity_now = false; - break; - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - /* avoid interference from generic hidinput handling */ - break; - - default: - /* fallback to the generic hidinput handling */ - return 0; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct quanta_data *td; - - td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); - if (!td) { - dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n"); - return -ENOMEM; - } - td->valid = false; - td->activity = false; - td->activity_now = false; - td->first = false; - hid_set_drvdata(hdev, td); - - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret) - kfree(td); - - return ret; -} - -static void quanta_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id quanta_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, - USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, - USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, - { } -}; -MODULE_DEVICE_TABLE(hid, quanta_devices); - -static const struct hid_usage_id quanta_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver quanta_driver = { - .name = "quanta-touch", - .id_table = quanta_devices, - .probe = quanta_probe, - .remove = quanta_remove, - .input_mapping = quanta_input_mapping, - .input_mapped = quanta_input_mapped, - .usage_table = quanta_grabbed_usages, - .event = quanta_event, -}; - -static int __init quanta_init(void) -{ - return hid_register_driver(&quanta_driver); -} - -static void __exit quanta_exit(void) -{ - hid_unregister_driver(&quanta_driver); -} - -module_init(quanta_init); -module_exit(quanta_exit); - diff --git a/trunk/drivers/hid/hid-sony.c b/trunk/drivers/hid/hid-sony.c index 9bf00d77d92b..4e8450228a24 100644 --- a/trunk/drivers/hid/hid-sony.c +++ b/trunk/drivers/hid/hid-sony.c @@ -48,7 +48,7 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, * to "operational". Without this, the ps3 controller will not report any * events. */ -static int sony_set_operational_usb(struct hid_device *hdev) +static int sony_set_operational(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); struct usb_device *dev = interface_to_usbdev(intf); @@ -73,12 +73,6 @@ static int sony_set_operational_usb(struct hid_device *hdev) return ret; } -static int sony_set_operational_bt(struct hid_device *hdev) -{ - unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 }; - return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); -} - static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -87,7 +81,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc = kzalloc(sizeof(*sc), GFP_KERNEL); if (sc == NULL) { - dev_err(&hdev->dev, "can't alloc sony descriptor\n"); + dev_err(&hdev->dev, "can't alloc apple descriptor\n"); return -ENOMEM; } @@ -107,17 +101,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_free; } - switch (hdev->bus) { - case BUS_USB: - ret = sony_set_operational_usb(hdev); - break; - case BUS_BLUETOOTH: - ret = sony_set_operational_bt(hdev); - break; - default: - ret = 0; - } - + ret = sony_set_operational(hdev); if (ret < 0) goto err_stop; @@ -137,7 +121,6 @@ static void sony_remove(struct hid_device *hdev) static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), .driver_data = VAIO_RDESC_CONSTANT }, { } diff --git a/trunk/drivers/hid/hid-stantum.c b/trunk/drivers/hid/hid-stantum.c deleted file mode 100644 index 2e592a06654e..000000000000 --- a/trunk/drivers/hid/hid-stantum.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * HID driver for Stantum multitouch panels - * - * Copyright (c) 2009 Stephane Chatty - * - */ - -/* - * 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 -#include -#include - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("Stantum HID multitouch panels"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct stantum_data { - __s32 x, y, z, w, h; /* x, y, pressure, width, height */ - __u16 id; /* touch id */ - bool valid; /* valid finger data, or just placeholder? */ - bool first; /* first finger in the HID packet? */ - bool activity; /* at least one active finger so far? */ -}; - -static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_INRANGE: - case HID_DG_CONFIDENCE: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - return -1; - - case HID_DG_TIPSWITCH: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - - case HID_DG_WIDTH: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); - return 1; - case HID_DG_HEIGHT: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); - input_set_abs_params(hi->input, ABS_MT_ORIENTATION, - 1, 1, 0, 0); - return 1; - case HID_DG_TIPPRESSURE: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_PRESSURE); - return 1; - - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - - } - return 0; - - case 0xff000000: - /* no input-oriented meaning */ - return -1; - } - - return 0; -} - -static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole finger has been parsed, - * so that it can decide what to send to the input layer. - */ -static void stantum_filter_event(struct stantum_data *sd, - struct input_dev *input) -{ - bool wide; - - if (!sd->valid) { - /* - * touchscreen emulation: if the first finger is not valid and - * there previously was finger activity, this is a release - */ - if (sd->first && sd->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - sd->activity = false; - } - return; - } - - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y); - - wide = (sd->w > sd->h); - input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); - input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h); - input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w); - - input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z); - - input_mt_sync(input); - sd->valid = false; - - /* touchscreen emulation */ - if (sd->first) { - if (!sd->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - sd->activity = true; - } - input_event(input, EV_ABS, ABS_X, sd->x); - input_event(input, EV_ABS, ABS_Y, sd->y); - } - sd->first = false; -} - - -static int stantum_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct stantum_data *sd = hid_get_drvdata(hid); - - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - - switch (usage->hid) { - case HID_DG_INRANGE: - /* this is the last field in a finger */ - stantum_filter_event(sd, input); - break; - case HID_DG_WIDTH: - sd->w = value; - break; - case HID_DG_HEIGHT: - sd->h = value; - break; - case HID_GD_X: - sd->x = value; - break; - case HID_GD_Y: - sd->y = value; - break; - case HID_DG_TIPPRESSURE: - sd->z = value; - break; - case HID_DG_CONTACTID: - sd->id = value; - break; - case HID_DG_CONFIDENCE: - sd->valid = !!value; - break; - case 0xff000002: - /* this comes only before the first finger */ - sd->first = true; - break; - - default: - /* ignore the others */ - return 1; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int stantum_probe(struct hid_device *hdev, - const struct hid_device_id *id) -{ - int ret; - struct stantum_data *sd; - - sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL); - if (!sd) { - dev_err(&hdev->dev, "cannot allocate Stantum data\n"); - return -ENOMEM; - } - sd->valid = false; - sd->first = false; - sd->activity = false; - hid_set_drvdata(hdev, sd); - - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret) - kfree(sd); - - return ret; -} - -static void stantum_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id stantum_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, - { } -}; -MODULE_DEVICE_TABLE(hid, stantum_devices); - -static const struct hid_usage_id stantum_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver stantum_driver = { - .name = "stantum", - .id_table = stantum_devices, - .probe = stantum_probe, - .remove = stantum_remove, - .input_mapping = stantum_input_mapping, - .input_mapped = stantum_input_mapped, - .usage_table = stantum_grabbed_usages, - .event = stantum_event, -}; - -static int __init stantum_init(void) -{ - return hid_register_driver(&stantum_driver); -} - -static void __exit stantum_exit(void) -{ - hid_unregister_driver(&stantum_driver); -} - -module_init(stantum_init); -module_exit(stantum_exit); - diff --git a/trunk/drivers/hid/hid-wacom.c b/trunk/drivers/hid/hid-wacom.c index 8d3b46f5d149..12dcda529201 100644 --- a/trunk/drivers/hid/hid-wacom.c +++ b/trunk/drivers/hid/hid-wacom.c @@ -156,9 +156,7 @@ static int wacom_probe(struct hid_device *hdev, struct hid_input *hidinput; struct input_dev *input; struct wacom_data *wdata; - char rep_data[2]; int ret; - int limit; wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); if (wdata == NULL) { @@ -168,7 +166,6 @@ static int wacom_probe(struct hid_device *hdev, hid_set_drvdata(hdev, wdata); - /* Parse the HID report now */ ret = hid_parse(hdev); if (ret) { dev_err(&hdev->dev, "parse failed\n"); @@ -181,31 +178,6 @@ static int wacom_probe(struct hid_device *hdev, goto err_free; } - /* - * Note that if the raw queries fail, it's not a hard failure and it - * is safe to continue - */ - - /* Set Wacom mode2 */ - rep_data[0] = 0x03; rep_data[1] = 0x00; - limit = 3; - do { - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - } while (ret < 0 && limit-- > 0); - if (ret < 0) - dev_warn(&hdev->dev, "failed to poke device #1, %d\n", ret); - - /* 0x06 - high reporting speed, 0x05 - low speed */ - rep_data[0] = 0x06; rep_data[1] = 0x00; - limit = 3; - do { - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); - } while (ret < 0 && limit-- > 0); - if (ret < 0) - dev_warn(&hdev->dev, "failed to poke device #2, %d\n", ret); - hidinput = list_entry(hdev->inputs.next, struct hid_input, list); input = hidinput->input; diff --git a/trunk/drivers/hid/hidraw.c b/trunk/drivers/hid/hidraw.c index d04476700b7b..cdd136942bca 100644 --- a/trunk/drivers/hid/hidraw.c +++ b/trunk/drivers/hid/hidraw.c @@ -134,7 +134,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t goto out; } - ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); + ret = dev->hid_output_raw_report(dev, buf, count); out: kfree(buf); return ret; diff --git a/trunk/drivers/hid/usbhid/hid-core.c b/trunk/drivers/hid/usbhid/hid-core.c index 56d06cd8075b..e2997a8d5e1b 100644 --- a/trunk/drivers/hid/usbhid/hid-core.c +++ b/trunk/drivers/hid/usbhid/hid-core.c @@ -5,7 +5,7 @@ * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc * Copyright (c) 2007-2008 Oliver Neukum - * Copyright (c) 2006-2010 Jiri Kosina + * Copyright (c) 2006-2009 Jiri Kosina */ /* @@ -316,7 +316,6 @@ static int hid_submit_out(struct hid_device *hid) err_hid("usb_submit_urb(out) failed"); return -1; } - usbhid->last_out = jiffies; } else { /* * queue work to wake up the device. @@ -378,7 +377,6 @@ static int hid_submit_ctrl(struct hid_device *hid) err_hid("usb_submit_urb(ctrl) failed"); return -1; } - usbhid->last_ctrl = jiffies; } else { /* * queue work to wake up the device. @@ -514,20 +512,9 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re usbhid->out[usbhid->outhead].report = report; usbhid->outhead = head; - if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { + if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) if (hid_submit_out(hid)) clear_bit(HID_OUT_RUNNING, &usbhid->iofl); - } else { - /* - * the queue is known to run - * but an earlier request may be stuck - * we may need to time out - * no race because this is called under - * spinlock - */ - if (time_after(jiffies, usbhid->last_out + HZ * 5)) - usb_unlink_urb(usbhid->urbout); - } return; } @@ -548,20 +535,9 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re usbhid->ctrl[usbhid->ctrlhead].dir = dir; usbhid->ctrlhead = head; - if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { + if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) if (hid_submit_ctrl(hid)) clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); - } else { - /* - * the queue is known to run - * but an earlier request may be stuck - * we may need to time out - * no race because this is called under - * spinlock - */ - if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) - usb_unlink_urb(usbhid->urbctrl); - } } void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) @@ -798,8 +774,7 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) return 0; } -static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, - unsigned char report_type) +static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count) { struct usbhid_device *usbhid = hid->driver_data; struct usb_device *dev = hid_to_usb_dev(hid); @@ -810,7 +785,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), HID_REQ_SET_REPORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | *buf, + ((HID_OUTPUT_REPORT + 1) << 8) | *buf, interface->desc.bInterfaceNumber, buf + 1, count - 1, USB_CTRL_SET_TIMEOUT); @@ -1006,6 +981,9 @@ static int usbhid_start(struct hid_device *hid) spin_lock_init(&usbhid->lock); + usbhid->intf = intf; + usbhid->ifnum = interface->desc.bInterfaceNumber; + usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); if (!usbhid->urbctrl) { ret = -ENOMEM; @@ -1176,8 +1154,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * hid->driver_data = usbhid; usbhid->hid = hid; - usbhid->intf = intf; - usbhid->ifnum = interface->desc.bInterfaceNumber; ret = hid_add_device(hid); if (ret) { @@ -1366,7 +1342,7 @@ static int hid_reset_resume(struct usb_interface *intf) #endif /* CONFIG_PM */ -static const struct usb_device_id hid_usb_ids[] = { +static struct usb_device_id hid_usb_ids [] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, .bInterfaceClass = USB_INTERFACE_CLASS_HID }, { } /* Terminating entry */ diff --git a/trunk/drivers/hid/usbhid/hid-quirks.c b/trunk/drivers/hid/usbhid/hid-quirks.c index 7844280897d1..38773dc2821b 100644 --- a/trunk/drivers/hid/usbhid/hid-quirks.c +++ b/trunk/drivers/hid/usbhid/hid-quirks.c @@ -43,10 +43,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, - { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, @@ -59,7 +57,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, diff --git a/trunk/drivers/hid/usbhid/usbhid.h b/trunk/drivers/hid/usbhid/usbhid.h index ec20400c7f29..08f505ca2e3d 100644 --- a/trunk/drivers/hid/usbhid/usbhid.h +++ b/trunk/drivers/hid/usbhid/usbhid.h @@ -80,14 +80,12 @@ struct usbhid_device { unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ char *ctrlbuf; /* Control buffer */ dma_addr_t ctrlbuf_dma; /* Control buffer dma */ - unsigned long last_ctrl; /* record of last output for timeouts */ struct urb *urbout; /* Output URB */ struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ unsigned char outhead, outtail; /* Output pipe fifo head & tail */ char *outbuf; /* Output buffer */ dma_addr_t outbuf_dma; /* Output buffer dma */ - unsigned long last_out; /* record of last output for timeouts */ spinlock_t lock; /* fifo spinlock */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ diff --git a/trunk/drivers/macintosh/adb.c b/trunk/drivers/macintosh/adb.c index d840a109f833..23741cec45e3 100644 --- a/trunk/drivers/macintosh/adb.c +++ b/trunk/drivers/macintosh/adb.c @@ -322,8 +322,8 @@ static int __init adb_init(void) adb_controller = NULL; } else { #ifdef CONFIG_PPC - if (of_machine_is_compatible("AAPL,PowerBook1998") || - of_machine_is_compatible("PowerBook1,1")) + if (machine_is_compatible("AAPL,PowerBook1998") || + machine_is_compatible("PowerBook1,1")) sleepy_trackpad = 1; #endif /* CONFIG_PPC */ diff --git a/trunk/drivers/macintosh/therm_pm72.c b/trunk/drivers/macintosh/therm_pm72.c index 5738d8bf2d97..454bc501df3c 100644 --- a/trunk/drivers/macintosh/therm_pm72.c +++ b/trunk/drivers/macintosh/therm_pm72.c @@ -1899,7 +1899,7 @@ static int create_control_loops(void) */ if (rackmac) cpu_pid_type = CPU_PID_TYPE_RACKMAC; - else if (of_machine_is_compatible("PowerMac7,3") + else if (machine_is_compatible("PowerMac7,3") && (cpu_count > 1) && fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID && fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) { @@ -2234,10 +2234,10 @@ static int __init therm_pm72_init(void) { struct device_node *np; - rackmac = of_machine_is_compatible("RackMac3,1"); + rackmac = machine_is_compatible("RackMac3,1"); - if (!of_machine_is_compatible("PowerMac7,2") && - !of_machine_is_compatible("PowerMac7,3") && + if (!machine_is_compatible("PowerMac7,2") && + !machine_is_compatible("PowerMac7,3") && !rackmac) return -ENODEV; diff --git a/trunk/drivers/macintosh/therm_windtunnel.c b/trunk/drivers/macintosh/therm_windtunnel.c index 7fb8b4da35a7..ba48fd76396e 100644 --- a/trunk/drivers/macintosh/therm_windtunnel.c +++ b/trunk/drivers/macintosh/therm_windtunnel.c @@ -490,7 +490,7 @@ g4fan_init( void ) info = of_get_property(np, "thermal-info", NULL); of_node_put(np); - if( !info || !of_machine_is_compatible("PowerMac3,6") ) + if( !info || !machine_is_compatible("PowerMac3,6") ) return -ENODEV; if( info->id != 3 ) { diff --git a/trunk/drivers/macintosh/via-pmu-backlight.c b/trunk/drivers/macintosh/via-pmu-backlight.c index 4f3c4479c16a..a348bb0791d3 100644 --- a/trunk/drivers/macintosh/via-pmu-backlight.c +++ b/trunk/drivers/macintosh/via-pmu-backlight.c @@ -150,13 +150,13 @@ void __init pmu_backlight_init() /* Special case for the old PowerBook since I can't test on it */ autosave = - of_machine_is_compatible("AAPL,3400/2400") || - of_machine_is_compatible("AAPL,3500"); + machine_is_compatible("AAPL,3400/2400") || + machine_is_compatible("AAPL,3500"); if (!autosave && !pmac_has_backlight_type("pmu") && - !of_machine_is_compatible("AAPL,PowerBook1998") && - !of_machine_is_compatible("PowerBook1,1")) + !machine_is_compatible("AAPL,PowerBook1998") && + !machine_is_compatible("PowerBook1,1")) return; snprintf(name, sizeof(name), "pmubl"); diff --git a/trunk/drivers/macintosh/via-pmu.c b/trunk/drivers/macintosh/via-pmu.c index 42764849eb78..db379c381432 100644 --- a/trunk/drivers/macintosh/via-pmu.c +++ b/trunk/drivers/macintosh/via-pmu.c @@ -463,8 +463,8 @@ static int __init via_pmu_dev_init(void) #endif #ifdef CONFIG_PPC32 - if (of_machine_is_compatible("AAPL,3400/2400") || - of_machine_is_compatible("AAPL,3500")) { + if (machine_is_compatible("AAPL,3400/2400") || + machine_is_compatible("AAPL,3500")) { int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_MODEL, 0); pmu_battery_count = 1; @@ -472,8 +472,8 @@ static int __init via_pmu_dev_init(void) pmu_batteries[0].flags |= PMU_BATT_TYPE_COMET; else pmu_batteries[0].flags |= PMU_BATT_TYPE_HOOPER; - } else if (of_machine_is_compatible("AAPL,PowerBook1998") || - of_machine_is_compatible("PowerBook1,1")) { + } else if (machine_is_compatible("AAPL,PowerBook1998") || + machine_is_compatible("PowerBook1,1")) { pmu_battery_count = 2; pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; diff --git a/trunk/drivers/macintosh/windfarm_core.c b/trunk/drivers/macintosh/windfarm_core.c index 437f55c5d18d..075b4d99e354 100644 --- a/trunk/drivers/macintosh/windfarm_core.c +++ b/trunk/drivers/macintosh/windfarm_core.c @@ -468,9 +468,9 @@ static int __init windfarm_core_init(void) DBG("wf: core loaded\n"); /* Don't register on old machines that use therm_pm72 for now */ - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) return -ENODEV; platform_device_register(&wf_platform_device); return 0; diff --git a/trunk/drivers/macintosh/windfarm_cpufreq_clamp.c b/trunk/drivers/macintosh/windfarm_cpufreq_clamp.c index 1a77a7c97d0e..900aade06198 100644 --- a/trunk/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/trunk/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -76,9 +76,9 @@ static int __init wf_cpufreq_clamp_init(void) struct wf_control *clamp; /* Don't register on old machines that use therm_pm72 for now */ - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) return -ENODEV; clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); diff --git a/trunk/drivers/macintosh/windfarm_lm75_sensor.c b/trunk/drivers/macintosh/windfarm_lm75_sensor.c index d8257d35afde..ed6426a10773 100644 --- a/trunk/drivers/macintosh/windfarm_lm75_sensor.c +++ b/trunk/drivers/macintosh/windfarm_lm75_sensor.c @@ -239,9 +239,9 @@ static struct i2c_driver wf_lm75_driver = { static int __init wf_lm75_sensor_init(void) { /* Don't register on old machines that use therm_pm72 for now */ - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) return -ENODEV; return i2c_add_driver(&wf_lm75_driver); } diff --git a/trunk/drivers/macintosh/windfarm_max6690_sensor.c b/trunk/drivers/macintosh/windfarm_max6690_sensor.c index b486eb929fde..a67b349319e9 100644 --- a/trunk/drivers/macintosh/windfarm_max6690_sensor.c +++ b/trunk/drivers/macintosh/windfarm_max6690_sensor.c @@ -188,9 +188,9 @@ static struct i2c_driver wf_max6690_driver = { static int __init wf_max6690_sensor_init(void) { /* Don't register on old machines that use therm_pm72 for now */ - if (of_machine_is_compatible("PowerMac7,2") || - of_machine_is_compatible("PowerMac7,3") || - of_machine_is_compatible("RackMac3,1")) + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) return -ENODEV; return i2c_add_driver(&wf_max6690_driver); } diff --git a/trunk/drivers/macintosh/windfarm_pm112.c b/trunk/drivers/macintosh/windfarm_pm112.c index e0ee80700cde..73d695dc9e50 100644 --- a/trunk/drivers/macintosh/windfarm_pm112.c +++ b/trunk/drivers/macintosh/windfarm_pm112.c @@ -676,7 +676,7 @@ static int __init wf_pm112_init(void) { struct device_node *cpu; - if (!of_machine_is_compatible("PowerMac11,2")) + if (!machine_is_compatible("PowerMac11,2")) return -ENODEV; /* Count the number of CPU cores */ diff --git a/trunk/drivers/macintosh/windfarm_pm121.c b/trunk/drivers/macintosh/windfarm_pm121.c index 947d4afa25ca..66ec4fb115bb 100644 --- a/trunk/drivers/macintosh/windfarm_pm121.c +++ b/trunk/drivers/macintosh/windfarm_pm121.c @@ -1008,7 +1008,7 @@ static int __init pm121_init(void) { int rc = -ENODEV; - if (of_machine_is_compatible("PowerMac12,1")) + if (machine_is_compatible("PowerMac12,1")) rc = pm121_init_pm(); if (rc == 0) { diff --git a/trunk/drivers/macintosh/windfarm_pm81.c b/trunk/drivers/macintosh/windfarm_pm81.c index 565d5b2adc95..abbe206474f5 100644 --- a/trunk/drivers/macintosh/windfarm_pm81.c +++ b/trunk/drivers/macintosh/windfarm_pm81.c @@ -779,8 +779,8 @@ static int __init wf_smu_init(void) { int rc = -ENODEV; - if (of_machine_is_compatible("PowerMac8,1") || - of_machine_is_compatible("PowerMac8,2")) + if (machine_is_compatible("PowerMac8,1") || + machine_is_compatible("PowerMac8,2")) rc = wf_init_pm(); if (rc == 0) { diff --git a/trunk/drivers/macintosh/windfarm_pm91.c b/trunk/drivers/macintosh/windfarm_pm91.c index bea99168ff35..764c525b2117 100644 --- a/trunk/drivers/macintosh/windfarm_pm91.c +++ b/trunk/drivers/macintosh/windfarm_pm91.c @@ -711,7 +711,7 @@ static int __init wf_smu_init(void) { int rc = -ENODEV; - if (of_machine_is_compatible("PowerMac9,1")) + if (machine_is_compatible("PowerMac9,1")) rc = wf_init_pm(); if (rc == 0) { diff --git a/trunk/drivers/macintosh/windfarm_smu_sensors.c b/trunk/drivers/macintosh/windfarm_smu_sensors.c index 3c193504bb80..9c567b93f417 100644 --- a/trunk/drivers/macintosh/windfarm_smu_sensors.c +++ b/trunk/drivers/macintosh/windfarm_smu_sensors.c @@ -363,9 +363,9 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) * I yet have to figure out what's up with 8,2 and will have to * adjust for later, unless we can 100% trust the SDB partition... */ - if ((of_machine_is_compatible("PowerMac8,1") || - of_machine_is_compatible("PowerMac8,2") || - of_machine_is_compatible("PowerMac9,1")) && + if ((machine_is_compatible("PowerMac8,1") || + machine_is_compatible("PowerMac8,2") || + machine_is_compatible("PowerMac9,1")) && cpuvcp_version >= 2) { pow->quadratic = 1; DBG("windfarm: CPU Power using quadratic transform\n"); diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 765543663a4f..d29bb532eccf 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -4006,21 +4006,11 @@ e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, } } - if (!buffer_info->dma) { + if (!buffer_info->dma) buffer_info->dma = pci_map_page(pdev, buffer_info->page, 0, buffer_info->length, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, buffer_info->dma)) { - put_page(buffer_info->page); - dev_kfree_skb(skb); - buffer_info->page = NULL; - buffer_info->skb = NULL; - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } - } rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@ -4111,13 +4101,6 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, skb->data, buffer_info->length, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, buffer_info->dma)) { - dev_kfree_skb(skb); - buffer_info->skb = NULL; - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } /* * XXX if it was allocated cleanly it will never map to a diff --git a/trunk/drivers/net/mace.c b/trunk/drivers/net/mace.c index 43aea91e3369..d9fbad386389 100644 --- a/trunk/drivers/net/mace.c +++ b/trunk/drivers/net/mace.c @@ -206,7 +206,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i mp->port_aaui = port_aaui; else { /* Apple Network Server uses the AAUI port */ - if (of_machine_is_compatible("AAPL,ShinerESB")) + if (machine_is_compatible("AAPL,ShinerESB")) mp->port_aaui = 1; else { #ifdef CONFIG_MACE_AAUI_PORT diff --git a/trunk/drivers/net/tc35815.c b/trunk/drivers/net/tc35815.c index d71c1976072e..75a669d48e5e 100644 --- a/trunk/drivers/net/tc35815.c +++ b/trunk/drivers/net/tc35815.c @@ -1437,6 +1437,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status, int limit) /* Transmit complete. */ lp->lstats.tx_ints++; tc35815_txdone(dev); + netif_wake_queue(dev); if (ret < 0) ret = 0; } diff --git a/trunk/drivers/net/usb/cdc_ether.c b/trunk/drivers/net/usb/cdc_ether.c index 5f3b9eaeb04f..4f27f022fbf7 100644 --- a/trunk/drivers/net/usb/cdc_ether.c +++ b/trunk/drivers/net/usb/cdc_ether.c @@ -583,11 +583,6 @@ static const struct usb_device_id products [] = { USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1049, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, -}, { - /* Ericsson C3607w ver 2 */ - USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190b, USB_CLASS_COMM, - USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &mbm_info, }, { /* Toshiba F3507g */ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c index 31462813bac0..9b4b8b5c7574 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2008,7 +2008,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index cffaae772d51..de45f308b744 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1125,7 +1125,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, scd_ssn , index, txq_id, txq->swq_id); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && @@ -1153,14 +1153,16 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, tx_resp->failure_frame); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) iwl_wake_queue(priv, txq_id); } - iwl_txq_check_empty(priv, sta_id, tid, txq_id); + if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) + iwl_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index f36f804804fc..d10bea64fce3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2744,8 +2744,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; - iwl_set_rxon_channel(priv, conf->channel); iwl_set_rxon_ht(priv, ht_conf); + iwl_set_rxon_channel(priv, conf->channel); iwl_set_flags_for_band(priv, conf->channel->band); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index b69e972671b2..27ca859e7453 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -446,8 +446,6 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c index 8f4071562857..87ce2bd292c7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -120,20 +120,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) EXPORT_SYMBOL(iwl_txq_update_write_ptr); -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed) -{ - if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - else { - IWL_ERR(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->stations[sta_id].tid[tid].tfds_in_queue, - freed); - priv->stations[sta_id].tid[tid].tfds_in_queue = 0; - } -} -EXPORT_SYMBOL(iwl_free_tfds_in_queue); - /** * iwl_tx_queue_free - Deallocate DMA queue. * @txq: Transmit queue to deallocate. @@ -1145,7 +1131,6 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) struct iwl_queue *q = &txq->q; struct iwl_tx_info *tx_info; int nfreed = 0; - struct ieee80211_hdr *hdr; if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " @@ -1160,16 +1145,13 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) tx_info = &txq->txb[txq->q.read_ptr]; iwl_tx_status(priv, tx_info->skb[0]); - - hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; - if (hdr && ieee80211_is_data_qos(hdr->frame_control)) - nfreed++; tx_info->skb[0] = NULL; if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); priv->cfg->ops->lib->txq_free_tfd(priv, txq); + nfreed++; } return nfreed; } @@ -1577,7 +1559,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { /* calculate mac80211 ampdu sw queue to wake */ int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && priv->mac80211_registered && diff --git a/trunk/drivers/of/Kconfig b/trunk/drivers/of/Kconfig index 7cecc8fea9bd..d2fa27c5c1b2 100644 --- a/trunk/drivers/of/Kconfig +++ b/trunk/drivers/of/Kconfig @@ -1,11 +1,3 @@ -config OF_FLATTREE - bool - depends on OF - -config OF_DYNAMIC - def_bool y - depends on OF && PPC_OF - config OF_DEVICE def_bool y depends on OF && (SPARC || PPC_OF || MICROBLAZE) diff --git a/trunk/drivers/of/Makefile b/trunk/drivers/of/Makefile index f232cc98ce00..bdfb5f5d4b06 100644 --- a/trunk/drivers/of/Makefile +++ b/trunk/drivers/of/Makefile @@ -1,5 +1,4 @@ obj-y = base.o -obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_DEVICE) += device.o platform.o obj-$(CONFIG_OF_GPIO) += gpio.o obj-$(CONFIG_OF_I2C) += of_i2c.o diff --git a/trunk/drivers/of/base.c b/trunk/drivers/of/base.c index cb96888d1427..e6627b2320f1 100644 --- a/trunk/drivers/of/base.c +++ b/trunk/drivers/of/base.c @@ -20,10 +20,8 @@ #include #include #include -#include struct device_node *allnodes; -struct device_node *of_chosen; /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. @@ -39,7 +37,7 @@ int of_n_addr_cells(struct device_node *np) np = np->parent; ip = of_get_property(np, "#address-cells", NULL); if (ip) - return be32_to_cpup(ip); + return *ip; } while (np->parent); /* No #address-cells property for the root node */ return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; @@ -55,88 +53,13 @@ int of_n_size_cells(struct device_node *np) np = np->parent; ip = of_get_property(np, "#size-cells", NULL); if (ip) - return be32_to_cpup(ip); + return *ip; } while (np->parent); /* No #size-cells property for the root node */ return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; } EXPORT_SYMBOL(of_n_size_cells); -#if !defined(CONFIG_SPARC) /* SPARC doesn't do ref counting (yet) */ -/** - * of_node_get - Increment refcount of a node - * @node: Node to inc refcount, NULL is supported to - * simplify writing of callers - * - * Returns node. - */ -struct device_node *of_node_get(struct device_node *node) -{ - if (node) - kref_get(&node->kref); - return node; -} -EXPORT_SYMBOL(of_node_get); - -static inline struct device_node *kref_to_device_node(struct kref *kref) -{ - return container_of(kref, struct device_node, kref); -} - -/** - * of_node_release - release a dynamically allocated node - * @kref: kref element of the node to be released - * - * In of_node_put() this function is passed to kref_put() - * as the destructor. - */ -static void of_node_release(struct kref *kref) -{ - struct device_node *node = kref_to_device_node(kref); - struct property *prop = node->properties; - - /* We should never be releasing nodes that haven't been detached. */ - if (!of_node_check_flag(node, OF_DETACHED)) { - pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); - dump_stack(); - kref_init(&node->kref); - return; - } - - if (!of_node_check_flag(node, OF_DYNAMIC)) - return; - - while (prop) { - struct property *next = prop->next; - kfree(prop->name); - kfree(prop->value); - kfree(prop); - prop = next; - - if (!prop) { - prop = node->deadprops; - node->deadprops = NULL; - } - } - kfree(node->full_name); - kfree(node->data); - kfree(node); -} - -/** - * of_node_put - Decrement refcount of a node - * @node: Node to dec refcount, NULL is supported to - * simplify writing of callers - * - */ -void of_node_put(struct device_node *node) -{ - if (node) - kref_put(&node->kref, of_node_release); -} -EXPORT_SYMBOL(of_node_put); -#endif /* !CONFIG_SPARC */ - struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) @@ -220,27 +143,6 @@ int of_device_is_compatible(const struct device_node *device, } EXPORT_SYMBOL(of_device_is_compatible); -/** - * of_machine_is_compatible - Test root of device tree for a given compatible value - * @compat: compatible string to look for in root node's compatible property. - * - * Returns true if the root node has the given value in its - * compatible property. - */ -int of_machine_is_compatible(const char *compat) -{ - struct device_node *root; - int rc = 0; - - root = of_find_node_by_path("/"); - if (root) { - rc = of_device_is_compatible(root, compat); - of_node_put(root); - } - return rc; -} -EXPORT_SYMBOL(of_machine_is_compatible); - /** * of_device_is_available - check if a device is available for use * @@ -616,27 +518,6 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) } EXPORT_SYMBOL_GPL(of_modalias_node); -/** - * of_find_node_by_phandle - Find a node given a phandle - * @handle: phandle of the node to find - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_phandle(phandle handle) -{ - struct device_node *np; - - read_lock(&devtree_lock); - for (np = allnodes; np; np = np->allnext) - if (np->phandle == handle) - break; - of_node_get(np); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_node_by_phandle); - /** * of_parse_phandle - Resolve a phandle property to a device_node pointer * @np: Pointer to device node holding phandle property @@ -697,8 +578,8 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const void **out_args) { int ret = -EINVAL; - const __be32 *list; - const __be32 *list_end; + const u32 *list; + const u32 *list_end; int size; int cur_index = 0; struct device_node *node = NULL; @@ -712,7 +593,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, list_end = list + size / sizeof(*list); while (list < list_end) { - const __be32 *cells; + const u32 *cells; const phandle *phandle; phandle = list++; @@ -736,7 +617,7 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, goto err1; } - list += be32_to_cpup(cells); + list += *cells; if (list > list_end) { pr_debug("%s: insufficient arguments length\n", np->full_name); @@ -777,190 +658,3 @@ int of_parse_phandles_with_args(struct device_node *np, const char *list_name, return ret; } EXPORT_SYMBOL(of_parse_phandles_with_args); - -/** - * prom_add_property - Add a property to a node - */ -int prom_add_property(struct device_node *np, struct property *prop) -{ - struct property **next; - unsigned long flags; - - prop->next = NULL; - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (strcmp(prop->name, (*next)->name) == 0) { - /* duplicate ! don't insert it */ - write_unlock_irqrestore(&devtree_lock, flags); - return -1; - } - next = &(*next)->next; - } - *next = prop; - write_unlock_irqrestore(&devtree_lock, flags); - -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (np->pde) - proc_device_tree_add_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - -/** - * prom_remove_property - Remove a property from a node. - * - * Note that we don't actually remove it, since we have given out - * who-knows-how-many pointers to the data using get-property. - * Instead we just move the property to the "dead properties" - * list, so it won't be found any more. - */ -int prom_remove_property(struct device_node *np, struct property *prop) -{ - struct property **next; - unsigned long flags; - int found = 0; - - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == prop) { - /* found the node */ - *next = prop->next; - prop->next = np->deadprops; - np->deadprops = prop; - found = 1; - break; - } - next = &(*next)->next; - } - write_unlock_irqrestore(&devtree_lock, flags); - - if (!found) - return -ENODEV; - -#ifdef CONFIG_PROC_DEVICETREE - /* try to remove the proc node as well */ - if (np->pde) - proc_device_tree_remove_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - -/* - * prom_update_property - Update a property in a node. - * - * Note that we don't actually remove it, since we have given out - * who-knows-how-many pointers to the data using get-property. - * Instead we just move the property to the "dead properties" list, - * and add the new property to the property list - */ -int prom_update_property(struct device_node *np, - struct property *newprop, - struct property *oldprop) -{ - struct property **next; - unsigned long flags; - int found = 0; - - write_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == oldprop) { - /* found the node */ - newprop->next = oldprop->next; - *next = newprop; - oldprop->next = np->deadprops; - np->deadprops = oldprop; - found = 1; - break; - } - next = &(*next)->next; - } - write_unlock_irqrestore(&devtree_lock, flags); - - if (!found) - return -ENODEV; - -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (np->pde) - proc_device_tree_update_prop(np->pde, newprop, oldprop); -#endif /* CONFIG_PROC_DEVICETREE */ - - return 0; -} - -#if defined(CONFIG_OF_DYNAMIC) -/* - * Support for dynamic device trees. - * - * On some platforms, the device tree can be manipulated at runtime. - * The routines in this section support adding, removing and changing - * device tree nodes. - */ - -/** - * of_attach_node - Plug a device node into the tree and global list. - */ -void of_attach_node(struct device_node *np) -{ - unsigned long flags; - - write_lock_irqsave(&devtree_lock, flags); - np->sibling = np->parent->child; - np->allnext = allnodes; - np->parent->child = np; - allnodes = np; - write_unlock_irqrestore(&devtree_lock, flags); -} - -/** - * of_detach_node - "Unplug" a node from the device tree. - * - * The caller must hold a reference to the node. The memory associated with - * the node is not freed until its refcount goes to zero. - */ -void of_detach_node(struct device_node *np) -{ - struct device_node *parent; - unsigned long flags; - - write_lock_irqsave(&devtree_lock, flags); - - parent = np->parent; - if (!parent) - goto out_unlock; - - if (allnodes == np) - allnodes = np->allnext; - else { - struct device_node *prev; - for (prev = allnodes; - prev->allnext != np; - prev = prev->allnext) - ; - prev->allnext = np->allnext; - } - - if (parent->child == np) - parent->child = np->sibling; - else { - struct device_node *prevsib; - for (prevsib = np->parent->child; - prevsib->sibling != np; - prevsib = prevsib->sibling) - ; - prevsib->sibling = np->sibling; - } - - of_node_set_flag(np, OF_DETACHED); - -out_unlock: - write_unlock_irqrestore(&devtree_lock, flags); -} -#endif /* defined(CONFIG_OF_DYNAMIC) */ - diff --git a/trunk/drivers/of/fdt.c b/trunk/drivers/of/fdt.c deleted file mode 100644 index 406757a9d7ea..000000000000 --- a/trunk/drivers/of/fdt.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Functions for working with the Flattened Device Tree data format - * - * Copyright 2009 Benjamin Herrenschmidt, IBM Corp - * benh@kernel.crashing.org - * - * 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 -#include -#include -#include -#include -#include - -#ifdef CONFIG_PPC -#include -#endif /* CONFIG_PPC */ - -#include - -int __initdata dt_root_addr_cells; -int __initdata dt_root_size_cells; - -struct boot_param_header *initial_boot_params; - -char *find_flat_dt_string(u32 offset) -{ - return ((char *)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_strings) + offset; -} - -/** - * of_scan_flat_dt - scan flattened tree blob and call callback on each. - * @it: callback function - * @data: context data pointer - * - * This function is used to scan the flattened device-tree, it is - * used to extract the memory information at boot before we can - * unflatten the tree - */ -int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - int rc = 0; - int depth = -1; - - do { - u32 tag = be32_to_cpup((__be32 *)p); - char *pathp; - - p += 4; - if (tag == OF_DT_END_NODE) { - depth--; - continue; - } - if (tag == OF_DT_NOP) - continue; - if (tag == OF_DT_END) - break; - if (tag == OF_DT_PROP) { - u32 sz = be32_to_cpup((__be32 *)p); - p += 8; - if (be32_to_cpu(initial_boot_params->version) < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - p += sz; - p = _ALIGN(p, 4); - continue; - } - if (tag != OF_DT_BEGIN_NODE) { - pr_err("Invalid tag %x in flat device tree!\n", tag); - return -EINVAL; - } - depth++; - pathp = (char *)p; - p = _ALIGN(p + strlen(pathp) + 1, 4); - if ((*pathp) == '/') { - char *lp, *np; - for (lp = NULL, np = pathp; *np; np++) - if ((*np) == '/') - lp = np+1; - if (lp != NULL) - pathp = lp; - } - rc = it(p, pathp, depth, data); - if (rc != 0) - break; - } while (1); - - return rc; -} - -/** - * of_get_flat_dt_root - find the root node in the flat blob - */ -unsigned long __init of_get_flat_dt_root(void) -{ - unsigned long p = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - - while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) - p += 4; - BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); - p += 4; - return _ALIGN(p + strlen((char *)p) + 1, 4); -} - -/** - * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr - * - * This function can be used within scan_flattened_dt callback to get - * access to properties - */ -void *__init of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) -{ - unsigned long p = node; - - do { - u32 tag = be32_to_cpup((__be32 *)p); - u32 sz, noff; - const char *nstr; - - p += 4; - if (tag == OF_DT_NOP) - continue; - if (tag != OF_DT_PROP) - return NULL; - - sz = be32_to_cpup((__be32 *)p); - noff = be32_to_cpup((__be32 *)(p + 4)); - p += 8; - if (be32_to_cpu(initial_boot_params->version) < 0x10) - p = _ALIGN(p, sz >= 8 ? 8 : 4); - - nstr = find_flat_dt_string(noff); - if (nstr == NULL) { - pr_warning("Can't find property index name !\n"); - return NULL; - } - if (strcmp(name, nstr) == 0) { - if (size) - *size = sz; - return (void *)p; - } - p += sz; - p = _ALIGN(p, 4); - } while (1); -} - -/** - * of_flat_dt_is_compatible - Return true if given node has compat in compatible list - * @node: node to test - * @compat: compatible string to compare with compatible list. - */ -int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) -{ - const char *cp; - unsigned long cplen, l; - - cp = of_get_flat_dt_prop(node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncasecmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} - -static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, - unsigned long align) -{ - void *res; - - *mem = _ALIGN(*mem, align); - res = (void *)*mem; - *mem += size; - - return res; -} - -/** - * unflatten_dt_node - Alloc and populate a device_node from the flat tree - * @p: pointer to node in flat tree - * @dad: Parent struct device_node - * @allnextpp: pointer to ->allnext from last allocated device_node - * @fpsize: Size of the node path up at the current depth. - */ -unsigned long __init unflatten_dt_node(unsigned long mem, - unsigned long *p, - struct device_node *dad, - struct device_node ***allnextpp, - unsigned long fpsize) -{ - struct device_node *np; - struct property *pp, **prev_pp = NULL; - char *pathp; - u32 tag; - unsigned int l, allocl; - int has_name = 0; - int new_format = 0; - - tag = be32_to_cpup((__be32 *)(*p)); - if (tag != OF_DT_BEGIN_NODE) { - pr_err("Weird tag at start of node: %x\n", tag); - return mem; - } - *p += 4; - pathp = (char *)*p; - l = allocl = strlen(pathp) + 1; - *p = _ALIGN(*p + l, 4); - - /* version 0x10 has a more compact unit name here instead of the full - * path. we accumulate the full path size using "fpsize", we'll rebuild - * it later. We detect this because the first character of the name is - * not '/'. - */ - if ((*pathp) != '/') { - new_format = 1; - if (fpsize == 0) { - /* root node: special case. fpsize accounts for path - * plus terminating zero. root node only has '/', so - * fpsize should be 2, but we want to avoid the first - * level nodes to have two '/' so we use fpsize 1 here - */ - fpsize = 1; - allocl = 2; - } else { - /* account for '/' and path size minus terminal 0 - * already in 'l' - */ - fpsize += l; - allocl = fpsize; - } - } - - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, - __alignof__(struct device_node)); - if (allnextpp) { - memset(np, 0, sizeof(*np)); - np->full_name = ((char *)np) + sizeof(struct device_node); - if (new_format) { - char *fn = np->full_name; - /* rebuild full path for new format */ - if (dad && dad->parent) { - strcpy(fn, dad->full_name); -#ifdef DEBUG - if ((strlen(fn) + l + 1) != allocl) { - pr_debug("%s: p: %d, l: %d, a: %d\n", - pathp, (int)strlen(fn), - l, allocl); - } -#endif - fn += strlen(fn); - } - *(fn++) = '/'; - memcpy(fn, pathp, l); - } else - memcpy(np->full_name, pathp, l); - prev_pp = &np->properties; - **allnextpp = np; - *allnextpp = &np->allnext; - if (dad != NULL) { - np->parent = dad; - /* we temporarily use the next field as `last_child'*/ - if (dad->next == NULL) - dad->child = np; - else - dad->next->sibling = np; - dad->next = np; - } - kref_init(&np->kref); - } - while (1) { - u32 sz, noff; - char *pname; - - tag = be32_to_cpup((__be32 *)(*p)); - if (tag == OF_DT_NOP) { - *p += 4; - continue; - } - if (tag != OF_DT_PROP) - break; - *p += 4; - sz = be32_to_cpup((__be32 *)(*p)); - noff = be32_to_cpup((__be32 *)((*p) + 4)); - *p += 8; - if (be32_to_cpu(initial_boot_params->version) < 0x10) - *p = _ALIGN(*p, sz >= 8 ? 8 : 4); - - pname = find_flat_dt_string(noff); - if (pname == NULL) { - pr_info("Can't find property name in list !\n"); - break; - } - if (strcmp(pname, "name") == 0) - has_name = 1; - l = strlen(pname) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property), - __alignof__(struct property)); - if (allnextpp) { - /* We accept flattened tree phandles either in - * ePAPR-style "phandle" properties, or the - * legacy "linux,phandle" properties. If both - * appear and have different values, things - * will get weird. Don't do that. */ - if ((strcmp(pname, "phandle") == 0) || - (strcmp(pname, "linux,phandle") == 0)) { - if (np->phandle == 0) - np->phandle = *((u32 *)*p); - } - /* And we process the "ibm,phandle" property - * used in pSeries dynamic device tree - * stuff */ - if (strcmp(pname, "ibm,phandle") == 0) - np->phandle = *((u32 *)*p); - pp->name = pname; - pp->length = sz; - pp->value = (void *)*p; - *prev_pp = pp; - prev_pp = &pp->next; - } - *p = _ALIGN((*p) + sz, 4); - } - /* with version 0x10 we may not have the name property, recreate - * it here from the unit name if absent - */ - if (!has_name) { - char *p1 = pathp, *ps = pathp, *pa = NULL; - int sz; - - while (*p1) { - if ((*p1) == '@') - pa = p1; - if ((*p1) == '/') - ps = p1 + 1; - p1++; - } - if (pa < ps) - pa = p1; - sz = (pa - ps) + 1; - pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, - __alignof__(struct property)); - if (allnextpp) { - pp->name = "name"; - pp->length = sz; - pp->value = pp + 1; - *prev_pp = pp; - prev_pp = &pp->next; - memcpy(pp->value, ps, sz - 1); - ((char *)pp->value)[sz - 1] = 0; - pr_debug("fixed up name for %s -> %s\n", pathp, - (char *)pp->value); - } - } - if (allnextpp) { - *prev_pp = NULL; - np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - - if (!np->name) - np->name = ""; - if (!np->type) - np->type = ""; - } - while (tag == OF_DT_BEGIN_NODE) { - mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); - tag = be32_to_cpup((__be32 *)(*p)); - } - if (tag != OF_DT_END_NODE) { - pr_err("Weird tag at end of node: %x\n", tag); - return mem; - } - *p += 4; - return mem; -} - -#ifdef CONFIG_BLK_DEV_INITRD -/** - * early_init_dt_check_for_initrd - Decode initrd location from flat tree - * @node: reference to node containing initrd location ('chosen') - */ -void __init early_init_dt_check_for_initrd(unsigned long node) -{ - unsigned long start, end, len; - __be32 *prop; - - pr_debug("Looking for initrd properties... "); - - prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); - if (!prop) - return; - start = of_read_ulong(prop, len/4); - - prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); - if (!prop) - return; - end = of_read_ulong(prop, len/4); - - early_init_dt_setup_initrd_arch(start, end); - pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", start, end); -} -#else -inline void early_init_dt_check_for_initrd(unsigned long node) -{ -} -#endif /* CONFIG_BLK_DEV_INITRD */ - -/** - * early_init_dt_scan_root - fetch the top level address and size cells - */ -int __init early_init_dt_scan_root(unsigned long node, const char *uname, - int depth, void *data) -{ - __be32 *prop; - - if (depth != 0) - return 0; - - dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; - dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT; - - prop = of_get_flat_dt_prop(node, "#size-cells", NULL); - if (prop) - dt_root_size_cells = be32_to_cpup(prop); - pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); - - prop = of_get_flat_dt_prop(node, "#address-cells", NULL); - if (prop) - dt_root_addr_cells = be32_to_cpup(prop); - pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); - - /* break now */ - return 1; -} - -u64 __init dt_mem_next_cell(int s, __be32 **cellp) -{ - __be32 *p = *cellp; - - *cellp = p + s; - return of_read_number(p, s); -} - -/** - * early_init_dt_scan_memory - Look for an parse memory nodes - */ -int __init early_init_dt_scan_memory(unsigned long node, const char *uname, - int depth, void *data) -{ - char *type = of_get_flat_dt_prop(node, "device_type", NULL); - __be32 *reg, *endp; - unsigned long l; - - /* We are scanning "memory" nodes only */ - if (type == NULL) { - /* - * The longtrail doesn't have a device_type on the - * /memory node, so look for the node called /memory@0. - */ - if (depth != 1 || strcmp(uname, "memory@0") != 0) - return 0; - } else if (strcmp(type, "memory") != 0) - return 0; - - reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); - if (reg == NULL) - reg = of_get_flat_dt_prop(node, "reg", &l); - if (reg == NULL) - return 0; - - endp = reg + (l / sizeof(__be32)); - - pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", - uname, l, reg[0], reg[1], reg[2], reg[3]); - - while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { - u64 base, size; - - base = dt_mem_next_cell(dt_root_addr_cells, ®); - size = dt_mem_next_cell(dt_root_size_cells, ®); - - if (size == 0) - continue; - pr_debug(" - %llx , %llx\n", (unsigned long long)base, - (unsigned long long)size); - - early_init_dt_add_memory_arch(base, size); - } - - return 0; -} - -int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - int depth, void *data) -{ - unsigned long l; - char *p; - - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); - - if (depth != 1 || - (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) - return 0; - - early_init_dt_check_for_initrd(node); - - /* Retreive command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); - if (p != NULL && l > 0) - strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); - -#ifdef CONFIG_CMDLINE -#ifndef CONFIG_CMDLINE_FORCE - if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) -#endif - strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -#endif /* CONFIG_CMDLINE */ - - early_init_dt_scan_chosen_arch(node); - - pr_debug("Command line is: %s\n", cmd_line); - - /* break now */ - return 1; -} - -/** - * unflatten_device_tree - create tree of device_nodes from flat blob - * - * unflattens the device-tree passed by the firmware, creating the - * tree of struct device_node. It also fills the "name" and "type" - * pointers of the nodes so the normal device-tree walking functions - * can be used. - */ -void __init unflatten_device_tree(void) -{ - unsigned long start, mem, size; - struct device_node **allnextp = &allnodes; - - pr_debug(" -> unflatten_device_tree()\n"); - - /* First pass, scan for size */ - start = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - size = unflatten_dt_node(0, &start, NULL, NULL, 0); - size = (size | 3) + 1; - - pr_debug(" size is %lx, allocating...\n", size); - - /* Allocate memory for the expanded device tree */ - mem = early_init_dt_alloc_memory_arch(size + 4, - __alignof__(struct device_node)); - mem = (unsigned long) __va(mem); - - ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); - - pr_debug(" unflattening %lx...\n", mem); - - /* Second pass, do actual unflattening */ - start = ((unsigned long)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_dt_struct); - unflatten_dt_node(mem, &start, NULL, &allnextp, 0); - if (be32_to_cpup((__be32 *)start) != OF_DT_END) - pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start)); - if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef) - pr_warning("End of tree marker overwritten: %08x\n", - be32_to_cpu(((__be32 *)mem)[size / 4])); - *allnextp = NULL; - - /* Get pointer to OF "/chosen" node for use everywhere */ - of_chosen = of_find_node_by_path("/chosen"); - if (of_chosen == NULL) - of_chosen = of_find_node_by_path("/chosen@0"); - - pr_debug(" <- unflatten_device_tree()\n"); -} diff --git a/trunk/drivers/of/gpio.c b/trunk/drivers/of/gpio.c index 24c3606217f8..6eea601a9204 100644 --- a/trunk/drivers/of/gpio.c +++ b/trunk/drivers/of/gpio.c @@ -36,7 +36,7 @@ int of_get_gpio_flags(struct device_node *np, int index, struct of_gpio_chip *of_gc = NULL; int size; const void *gpio_spec; - const __be32 *gpio_cells; + const u32 *gpio_cells; ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index, &gc, &gpio_spec); @@ -55,7 +55,7 @@ int of_get_gpio_flags(struct device_node *np, int index, gpio_cells = of_get_property(gc, "#gpio-cells", &size); if (!gpio_cells || size != sizeof(*gpio_cells) || - be32_to_cpup(gpio_cells) != of_gc->gpio_cells) { + *gpio_cells != of_gc->gpio_cells) { pr_debug("%s: wrong #gpio-cells for %s\n", np->full_name, gc->full_name); ret = -EINVAL; @@ -127,8 +127,7 @@ EXPORT_SYMBOL(of_gpio_count); int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, const void *gpio_spec, enum of_gpio_flags *flags) { - const __be32 *gpio = gpio_spec; - const u32 n = be32_to_cpup(gpio); + const u32 *gpio = gpio_spec; /* * We're discouraging gpio_cells < 2, since that way you'll have to @@ -141,13 +140,13 @@ int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, return -EINVAL; } - if (n > of_gc->gc.ngpio) + if (*gpio > of_gc->gc.ngpio) return -EINVAL; if (flags) - *flags = be32_to_cpu(gpio[1]); + *flags = gpio[1]; - return n; + return *gpio; } EXPORT_SYMBOL(of_gpio_simple_xlate); diff --git a/trunk/drivers/of/of_i2c.c b/trunk/drivers/of/of_i2c.c index a3a708e590d0..fa65a2b2ae2e 100644 --- a/trunk/drivers/of/of_i2c.c +++ b/trunk/drivers/of/of_i2c.c @@ -25,7 +25,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, for_each_child_of_node(adap_node, node) { struct i2c_board_info info = {}; struct dev_archdata dev_ad = {}; - const __be32 *addr; + const u32 *addr; int len; if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) @@ -40,7 +40,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap, info.irq = irq_of_parse_and_map(node, 0); - info.addr = be32_to_cpup(addr); + info.addr = *addr; dev_archdata_set_node(&dev_ad, node); info.archdata = &dev_ad; diff --git a/trunk/drivers/of/of_mdio.c b/trunk/drivers/of/of_mdio.c index 18ecae4a4375..4b22ba568b19 100644 --- a/trunk/drivers/of/of_mdio.c +++ b/trunk/drivers/of/of_mdio.c @@ -51,7 +51,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) /* Loop over the child nodes and register a phy_device for each one */ for_each_child_of_node(np, child) { - const __be32 *addr; + const u32 *addr; int len; /* A PHY must have a reg property in the range [0-31] */ @@ -68,7 +68,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) mdio->irq[*addr] = PHY_POLL; } - phy = get_phy_device(mdio, be32_to_cpup(addr)); + phy = get_phy_device(mdio, *addr); if (!phy) { dev_err(&mdio->dev, "error probing PHY at address %i\n", *addr); @@ -160,7 +160,7 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, struct device_node *net_np; char bus_id[MII_BUS_ID_SIZE + 3]; struct phy_device *phy; - const __be32 *phy_id; + const u32 *phy_id; int sz; if (!dev->dev.parent) @@ -174,7 +174,7 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, if (!phy_id || sz < sizeof(*phy_id)) return NULL; - sprintf(bus_id, PHY_ID_FMT, "0", be32_to_cpu(phy_id[0])); + sprintf(bus_id, PHY_ID_FMT, "0", phy_id[0]); phy = phy_connect(dev, bus_id, hndlr, 0, iface); return IS_ERR(phy) ? NULL : phy; diff --git a/trunk/drivers/of/of_spi.c b/trunk/drivers/of/of_spi.c index f65f48b98448..bed0ed6dcdc1 100644 --- a/trunk/drivers/of/of_spi.c +++ b/trunk/drivers/of/of_spi.c @@ -23,7 +23,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) { struct spi_device *spi; struct device_node *nc; - const __be32 *prop; + const u32 *prop; int rc; int len; @@ -54,7 +54,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) spi_dev_put(spi); continue; } - spi->chip_select = be32_to_cpup(prop); + spi->chip_select = *prop; /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) @@ -72,7 +72,7 @@ void of_register_spi_devices(struct spi_master *master, struct device_node *np) spi_dev_put(spi); continue; } - spi->max_speed_hz = be32_to_cpup(prop); + spi->max_speed_hz = *prop; /* IRQ */ spi->irq = irq_of_parse_and_map(nc, 0); diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 446e4a94d7d3..dd64310a735e 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -1081,6 +1081,37 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) } EXPORT_SYMBOL(pci_scan_single_device); +static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) +{ + u16 cap; + unsigned pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) + return 0; + pci_read_config_word(dev, pos + 4, &cap); + return cap >> 8; +} + +static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) +{ + return (fn + 1) % 8; +} + +static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) +{ + return 0; +} + +static int only_one_child(struct pci_bus *bus) +{ + struct pci_dev *parent = bus->self; + if (!parent || !pci_is_pcie(parent)) + return 0; + if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) + return 1; + return 0; +} + /** * pci_scan_slot - scan a PCI slot on a bus for devices. * @bus: PCI bus to scan @@ -1094,21 +1125,28 @@ EXPORT_SYMBOL(pci_scan_single_device); */ int pci_scan_slot(struct pci_bus *bus, int devfn) { - int fn, nr = 0; + unsigned fn, nr = 0; struct pci_dev *dev; + unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; + + if (only_one_child(bus) && (devfn > 0)) + return 0; /* Already scanned the entire slot */ dev = pci_scan_single_device(bus, devfn); if (dev && !dev->is_added) /* new device? */ nr++; - if (dev && dev->multifunction) { - for (fn = 1; fn < 8; fn++) { - dev = pci_scan_single_device(bus, devfn + fn); - if (dev) { - if (!dev->is_added) - nr++; - dev->multifunction = 1; - } + if (pci_ari_enabled(bus)) + next_fn = next_ari_fn; + else if (dev && dev->multifunction) + next_fn = next_trad_fn; + + for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { + dev = pci_scan_single_device(bus, devfn + fn); + if (dev) { + if (!dev->is_added) + nr++; + dev->multifunction = 1; } } diff --git a/trunk/drivers/platform/x86/acer-wmi.c b/trunk/drivers/platform/x86/acer-wmi.c index 226b3e93498c..07d14dfdf0b4 100644 --- a/trunk/drivers/platform/x86/acer-wmi.c +++ b/trunk/drivers/platform/x86/acer-wmi.c @@ -934,7 +934,7 @@ static int __devinit acer_backlight_init(struct device *dev) acer_backlight_device = bd; bd->props.power = FB_BLANK_UNBLANK; - bd->props.brightness = read_brightness(bd); + bd->props.brightness = max_brightness; bd->props.max_brightness = max_brightness; backlight_update_status(bd); return 0; diff --git a/trunk/drivers/sbus/char/openprom.c b/trunk/drivers/sbus/char/openprom.c index fc2f676e984d..75ac19b1192f 100644 --- a/trunk/drivers/sbus/char/openprom.c +++ b/trunk/drivers/sbus/char/openprom.c @@ -233,7 +233,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp ph = 0; if (dp) - ph = dp->phandle; + ph = dp->node; data->current_node = dp; *((int *) op->oprom_array) = ph; @@ -256,7 +256,7 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp dp = pci_device_to_OF_node(pdev); data->current_node = dp; - *((int *)op->oprom_array) = dp->phandle; + *((int *)op->oprom_array) = dp->node; op->oprom_size = sizeof(int); err = copyout(argp, op, bufsize + sizeof(int)); @@ -273,7 +273,7 @@ static int oprompath2node(void __user *argp, struct device_node *dp, struct open dp = of_find_node_by_path(op->oprom_array); if (dp) - ph = dp->phandle; + ph = dp->node; data->current_node = dp; *((int *)op->oprom_array) = ph; op->oprom_size = sizeof(int); @@ -540,7 +540,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp) } } if (dp) - nd = dp->phandle; + nd = dp->node; if (copy_to_user(argp, &nd, sizeof(phandle))) return -EFAULT; @@ -570,7 +570,7 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, case OPIOCGETOPTNODE: BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); - if (copy_to_user(argp, &options_node->phandle, sizeof(phandle))) + if (copy_to_user(argp, &options_node->node, sizeof(phandle))) return -EFAULT; return 0; diff --git a/trunk/drivers/serial/pmac_zilog.c b/trunk/drivers/serial/pmac_zilog.c index 3e2ae4807ae2..683e66f18e8c 100644 --- a/trunk/drivers/serial/pmac_zilog.c +++ b/trunk/drivers/serial/pmac_zilog.c @@ -2031,9 +2031,9 @@ static int __init pmz_console_setup(struct console *co, char *options) /* * XServe's default to 57600 bps */ - if (of_machine_is_compatible("RackMac1,1") - || of_machine_is_compatible("RackMac1,2") - || of_machine_is_compatible("MacRISC4")) + if (machine_is_compatible("RackMac1,1") + || machine_is_compatible("RackMac1,2") + || machine_is_compatible("MacRISC4")) baud = 57600; /* diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index 0fee95cd9a49..f55eb0107336 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -100,23 +100,6 @@ config SPI_BUTTERFLY inexpensive battery powered microcontroller evaluation board. This same cable can be used to flash new firmware. -config SPI_COLDFIRE_QSPI - tristate "Freescale Coldfire QSPI controller" - depends on (M520x || M523x || M5249 || M527x || M528x || M532x) - help - This enables support for the Coldfire QSPI controller in master - mode. - - This driver can also be built as a module. If so, the module - will be called coldfire_qspi. - -config SPI_DAVINCI - tristate "SPI controller driver for DaVinci/DA8xx SoC's" - depends on SPI_MASTER && ARCH_DAVINCI - select SPI_BITBANG - help - SPI master controller for DaVinci and DA8xx SPI modules. - config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GENERIC_GPIO @@ -325,7 +308,7 @@ config SPI_NUC900 # config SPI_DESIGNWARE - tristate "DesignWare SPI controller core support" + bool "DesignWare SPI controller core support" depends on SPI_MASTER help general driver for SPI controller core from DesignWare @@ -334,10 +317,6 @@ config SPI_DW_PCI tristate "PCI interface driver for DW SPI core" depends on SPI_DESIGNWARE && PCI -config SPI_DW_MMIO - tristate "Memory-mapped io interface driver for DW SPI core" - depends on SPI_DESIGNWARE && HAVE_CLK - # # There are lots of SPI device types, with sensors and memory # being probably the most widely used ones. diff --git a/trunk/drivers/spi/Makefile b/trunk/drivers/spi/Makefile index d7d0f89b797b..f3d2810ba11c 100644 --- a/trunk/drivers/spi/Makefile +++ b/trunk/drivers/spi/Makefile @@ -16,11 +16,8 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o obj-$(CONFIG_SPI_AU1550) += au1550_spi.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o -obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o -obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o -obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o obj-$(CONFIG_SPI_GPIO) += spi_gpio.o obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o diff --git a/trunk/drivers/spi/coldfire_qspi.c b/trunk/drivers/spi/coldfire_qspi.c deleted file mode 100644 index 59be3efe0636..000000000000 --- a/trunk/drivers/spi/coldfire_qspi.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Freescale/Motorola Coldfire Queued SPI driver - * - * Copyright 2010 Steven 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRIVER_NAME "mcfqspi" - -#define MCFQSPI_BUSCLK (MCF_BUSCLK / 2) - -#define MCFQSPI_QMR 0x00 -#define MCFQSPI_QMR_MSTR 0x8000 -#define MCFQSPI_QMR_CPOL 0x0200 -#define MCFQSPI_QMR_CPHA 0x0100 -#define MCFQSPI_QDLYR 0x04 -#define MCFQSPI_QDLYR_SPE 0x8000 -#define MCFQSPI_QWR 0x08 -#define MCFQSPI_QWR_HALT 0x8000 -#define MCFQSPI_QWR_WREN 0x4000 -#define MCFQSPI_QWR_CSIV 0x1000 -#define MCFQSPI_QIR 0x0C -#define MCFQSPI_QIR_WCEFB 0x8000 -#define MCFQSPI_QIR_ABRTB 0x4000 -#define MCFQSPI_QIR_ABRTL 0x1000 -#define MCFQSPI_QIR_WCEFE 0x0800 -#define MCFQSPI_QIR_ABRTE 0x0400 -#define MCFQSPI_QIR_SPIFE 0x0100 -#define MCFQSPI_QIR_WCEF 0x0008 -#define MCFQSPI_QIR_ABRT 0x0004 -#define MCFQSPI_QIR_SPIF 0x0001 -#define MCFQSPI_QAR 0x010 -#define MCFQSPI_QAR_TXBUF 0x00 -#define MCFQSPI_QAR_RXBUF 0x10 -#define MCFQSPI_QAR_CMDBUF 0x20 -#define MCFQSPI_QDR 0x014 -#define MCFQSPI_QCR 0x014 -#define MCFQSPI_QCR_CONT 0x8000 -#define MCFQSPI_QCR_BITSE 0x4000 -#define MCFQSPI_QCR_DT 0x2000 - -struct mcfqspi { - void __iomem *iobase; - int irq; - struct clk *clk; - struct mcfqspi_cs_control *cs_control; - - wait_queue_head_t waitq; - - struct work_struct work; - struct workqueue_struct *workq; - spinlock_t lock; - struct list_head msgq; -}; - -static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QMR); -} - -static void mcfqspi_wr_qdlyr(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QDLYR); -} - -static u16 mcfqspi_rd_qdlyr(struct mcfqspi *mcfqspi) -{ - return readw(mcfqspi->iobase + MCFQSPI_QDLYR); -} - -static void mcfqspi_wr_qwr(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QWR); -} - -static void mcfqspi_wr_qir(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QIR); -} - -static void mcfqspi_wr_qar(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QAR); -} - -static void mcfqspi_wr_qdr(struct mcfqspi *mcfqspi, u16 val) -{ - writew(val, mcfqspi->iobase + MCFQSPI_QDR); -} - -static u16 mcfqspi_rd_qdr(struct mcfqspi *mcfqspi) -{ - return readw(mcfqspi->iobase + MCFQSPI_QDR); -} - -static void mcfqspi_cs_select(struct mcfqspi *mcfqspi, u8 chip_select, - bool cs_high) -{ - mcfqspi->cs_control->select(mcfqspi->cs_control, chip_select, cs_high); -} - -static void mcfqspi_cs_deselect(struct mcfqspi *mcfqspi, u8 chip_select, - bool cs_high) -{ - mcfqspi->cs_control->deselect(mcfqspi->cs_control, chip_select, cs_high); -} - -static int mcfqspi_cs_setup(struct mcfqspi *mcfqspi) -{ - return (mcfqspi->cs_control && mcfqspi->cs_control->setup) ? - mcfqspi->cs_control->setup(mcfqspi->cs_control) : 0; -} - -static void mcfqspi_cs_teardown(struct mcfqspi *mcfqspi) -{ - if (mcfqspi->cs_control && mcfqspi->cs_control->teardown) - mcfqspi->cs_control->teardown(mcfqspi->cs_control); -} - -static u8 mcfqspi_qmr_baud(u32 speed_hz) -{ - return clamp((MCFQSPI_BUSCLK + speed_hz - 1) / speed_hz, 2u, 255u); -} - -static bool mcfqspi_qdlyr_spe(struct mcfqspi *mcfqspi) -{ - return mcfqspi_rd_qdlyr(mcfqspi) & MCFQSPI_QDLYR_SPE; -} - -static irqreturn_t mcfqspi_irq_handler(int this_irq, void *dev_id) -{ - struct mcfqspi *mcfqspi = dev_id; - - /* clear interrupt */ - mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE | MCFQSPI_QIR_SPIF); - wake_up(&mcfqspi->waitq); - - return IRQ_HANDLED; -} - -static void mcfqspi_transfer_msg8(struct mcfqspi *mcfqspi, unsigned count, - const u8 *txbuf, u8 *rxbuf) -{ - unsigned i, n, offset = 0; - - n = min(count, 16u); - - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF); - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE); - - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF); - if (txbuf) - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, *txbuf++); - else - for (i = 0; i < count; ++i) - mcfqspi_wr_qdr(mcfqspi, 0); - - count -= n; - if (count) { - u16 qwr = 0xf08; - mcfqspi_wr_qwr(mcfqspi, 0x700); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - - do { - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - mcfqspi_wr_qwr(mcfqspi, qwr); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, - MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < 8; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - } - n = min(count, 8u); - if (txbuf) { - mcfqspi_wr_qar(mcfqspi, - MCFQSPI_QAR_TXBUF + offset); - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, *txbuf++); - } - qwr = (offset ? 0x808 : 0) + ((n - 1) << 8); - offset ^= 8; - count -= n; - } while (count); - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - mcfqspi_wr_qwr(mcfqspi, qwr); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < 8; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - offset ^= 8; - } - } else { - mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - } - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < n; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - } -} - -static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count, - const u16 *txbuf, u16 *rxbuf) -{ - unsigned i, n, offset = 0; - - n = min(count, 16u); - - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF); - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE); - - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF); - if (txbuf) - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, *txbuf++); - else - for (i = 0; i < count; ++i) - mcfqspi_wr_qdr(mcfqspi, 0); - - count -= n; - if (count) { - u16 qwr = 0xf08; - mcfqspi_wr_qwr(mcfqspi, 0x700); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - - do { - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - mcfqspi_wr_qwr(mcfqspi, qwr); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, - MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < 8; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - } - n = min(count, 8u); - if (txbuf) { - mcfqspi_wr_qar(mcfqspi, - MCFQSPI_QAR_TXBUF + offset); - for (i = 0; i < n; ++i) - mcfqspi_wr_qdr(mcfqspi, *txbuf++); - } - qwr = (offset ? 0x808 : 0x000) + ((n - 1) << 8); - offset ^= 8; - count -= n; - } while (count); - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - mcfqspi_wr_qwr(mcfqspi, qwr); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < 8; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - offset ^= 8; - } - } else { - mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8); - mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE); - } - wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi)); - if (rxbuf) { - mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset); - for (i = 0; i < n; ++i) - *rxbuf++ = mcfqspi_rd_qdr(mcfqspi); - } -} - -static void mcfqspi_work(struct work_struct *work) -{ - struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work); - unsigned long flags; - - spin_lock_irqsave(&mcfqspi->lock, flags); - while (!list_empty(&mcfqspi->msgq)) { - struct spi_message *msg; - struct spi_device *spi; - struct spi_transfer *xfer; - int status = 0; - - msg = container_of(mcfqspi->msgq.next, struct spi_message, - queue); - - list_del_init(&mcfqspi->msgq); - spin_unlock_irqrestore(&mcfqspi->lock, flags); - - spi = msg->spi; - - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - bool cs_high = spi->mode & SPI_CS_HIGH; - u16 qmr = MCFQSPI_QMR_MSTR; - - if (xfer->bits_per_word) - qmr |= xfer->bits_per_word << 10; - else - qmr |= spi->bits_per_word << 10; - if (spi->mode & SPI_CPHA) - qmr |= MCFQSPI_QMR_CPHA; - if (spi->mode & SPI_CPOL) - qmr |= MCFQSPI_QMR_CPOL; - if (xfer->speed_hz) - qmr |= mcfqspi_qmr_baud(xfer->speed_hz); - else - qmr |= mcfqspi_qmr_baud(spi->max_speed_hz); - mcfqspi_wr_qmr(mcfqspi, qmr); - - mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high); - - mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE); - if ((xfer->bits_per_word ? xfer->bits_per_word : - spi->bits_per_word) == 8) - mcfqspi_transfer_msg8(mcfqspi, xfer->len, - xfer->tx_buf, - xfer->rx_buf); - else - mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2, - xfer->tx_buf, - xfer->rx_buf); - mcfqspi_wr_qir(mcfqspi, 0); - - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); - if (xfer->cs_change) { - if (!list_is_last(&xfer->transfer_list, - &msg->transfers)) - mcfqspi_cs_deselect(mcfqspi, - spi->chip_select, - cs_high); - } else { - if (list_is_last(&xfer->transfer_list, - &msg->transfers)) - mcfqspi_cs_deselect(mcfqspi, - spi->chip_select, - cs_high); - } - msg->actual_length += xfer->len; - } - msg->status = status; - msg->complete(msg->context); - - spin_lock_irqsave(&mcfqspi->lock, flags); - } - spin_unlock_irqrestore(&mcfqspi->lock, flags); -} - -static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct mcfqspi *mcfqspi; - struct spi_transfer *xfer; - unsigned long flags; - - mcfqspi = spi_master_get_devdata(spi->master); - - list_for_each_entry(xfer, &msg->transfers, transfer_list) { - if (xfer->bits_per_word && ((xfer->bits_per_word < 8) - || (xfer->bits_per_word > 16))) { - dev_dbg(&spi->dev, - "%d bits per word is not supported\n", - xfer->bits_per_word); - goto fail; - } - if (xfer->speed_hz) { - u32 real_speed = MCFQSPI_BUSCLK / - mcfqspi_qmr_baud(xfer->speed_hz); - if (real_speed != xfer->speed_hz) - dev_dbg(&spi->dev, - "using speed %d instead of %d\n", - real_speed, xfer->speed_hz); - } - } - msg->status = -EINPROGRESS; - msg->actual_length = 0; - - spin_lock_irqsave(&mcfqspi->lock, flags); - list_add_tail(&msg->queue, &mcfqspi->msgq); - queue_work(mcfqspi->workq, &mcfqspi->work); - spin_unlock_irqrestore(&mcfqspi->lock, flags); - - return 0; -fail: - msg->status = -EINVAL; - return -EINVAL; -} - -static int mcfqspi_setup(struct spi_device *spi) -{ - if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) { - dev_dbg(&spi->dev, "%d bits per word is not supported\n", - spi->bits_per_word); - return -EINVAL; - } - if (spi->chip_select >= spi->master->num_chipselect) { - dev_dbg(&spi->dev, "%d chip select is out of range\n", - spi->chip_select); - return -EINVAL; - } - - mcfqspi_cs_deselect(spi_master_get_devdata(spi->master), - spi->chip_select, spi->mode & SPI_CS_HIGH); - - dev_dbg(&spi->dev, - "bits per word %d, chip select %d, speed %d KHz\n", - spi->bits_per_word, spi->chip_select, - (MCFQSPI_BUSCLK / mcfqspi_qmr_baud(spi->max_speed_hz)) - / 1000); - - return 0; -} - -static int __devinit mcfqspi_probe(struct platform_device *pdev) -{ - struct spi_master *master; - struct mcfqspi *mcfqspi; - struct resource *res; - struct mcfqspi_platform_data *pdata; - int status; - - master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi)); - if (master == NULL) { - dev_dbg(&pdev->dev, "spi_alloc_master failed\n"); - return -ENOMEM; - } - - mcfqspi = spi_master_get_devdata(master); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_dbg(&pdev->dev, "platform_get_resource failed\n"); - status = -ENXIO; - goto fail0; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_dbg(&pdev->dev, "request_mem_region failed\n"); - status = -EBUSY; - goto fail0; - } - - mcfqspi->iobase = ioremap(res->start, resource_size(res)); - if (!mcfqspi->iobase) { - dev_dbg(&pdev->dev, "ioremap failed\n"); - status = -ENOMEM; - goto fail1; - } - - mcfqspi->irq = platform_get_irq(pdev, 0); - if (mcfqspi->irq < 0) { - dev_dbg(&pdev->dev, "platform_get_irq failed\n"); - status = -ENXIO; - goto fail2; - } - - status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED, - pdev->name, mcfqspi); - if (status) { - dev_dbg(&pdev->dev, "request_irq failed\n"); - goto fail2; - } - - mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk"); - if (IS_ERR(mcfqspi->clk)) { - dev_dbg(&pdev->dev, "clk_get failed\n"); - status = PTR_ERR(mcfqspi->clk); - goto fail3; - } - clk_enable(mcfqspi->clk); - - mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent)); - if (!mcfqspi->workq) { - dev_dbg(&pdev->dev, "create_workqueue failed\n"); - status = -ENOMEM; - goto fail4; - } - INIT_WORK(&mcfqspi->work, mcfqspi_work); - spin_lock_init(&mcfqspi->lock); - INIT_LIST_HEAD(&mcfqspi->msgq); - init_waitqueue_head(&mcfqspi->waitq); - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_dbg(&pdev->dev, "platform data is missing\n"); - goto fail5; - } - master->bus_num = pdata->bus_num; - master->num_chipselect = pdata->num_chipselect; - - mcfqspi->cs_control = pdata->cs_control; - status = mcfqspi_cs_setup(mcfqspi); - if (status) { - dev_dbg(&pdev->dev, "error initializing cs_control\n"); - goto fail5; - } - - master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; - master->setup = mcfqspi_setup; - master->transfer = mcfqspi_transfer; - - platform_set_drvdata(pdev, master); - - status = spi_register_master(master); - if (status) { - dev_dbg(&pdev->dev, "spi_register_master failed\n"); - goto fail6; - } - dev_info(&pdev->dev, "Coldfire QSPI bus driver\n"); - - return 0; - -fail6: - mcfqspi_cs_teardown(mcfqspi); -fail5: - destroy_workqueue(mcfqspi->workq); -fail4: - clk_disable(mcfqspi->clk); - clk_put(mcfqspi->clk); -fail3: - free_irq(mcfqspi->irq, mcfqspi); -fail2: - iounmap(mcfqspi->iobase); -fail1: - release_mem_region(res->start, resource_size(res)); -fail0: - spi_master_put(master); - - dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n"); - - return status; -} - -static int __devexit mcfqspi_remove(struct platform_device *pdev) -{ - struct spi_master *master = platform_get_drvdata(pdev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - /* disable the hardware (set the baud rate to 0) */ - mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); - - platform_set_drvdata(pdev, NULL); - mcfqspi_cs_teardown(mcfqspi); - destroy_workqueue(mcfqspi->workq); - clk_disable(mcfqspi->clk); - clk_put(mcfqspi->clk); - free_irq(mcfqspi->irq, mcfqspi); - iounmap(mcfqspi->iobase); - release_mem_region(res->start, resource_size(res)); - spi_unregister_master(master); - spi_master_put(master); - - return 0; -} - -#ifdef CONFIG_PM - -static int mcfqspi_suspend(struct device *dev) -{ - struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev)); - - clk_disable(mcfqspi->clk); - - return 0; -} - -static int mcfqspi_resume(struct device *dev) -{ - struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev)); - - clk_enable(mcfqspi->clk); - - return 0; -} - -static struct dev_pm_ops mcfqspi_dev_pm_ops = { - .suspend = mcfqspi_suspend, - .resume = mcfqspi_resume, -}; - -#define MCFQSPI_DEV_PM_OPS (&mcfqspi_dev_pm_ops) -#else -#define MCFQSPI_DEV_PM_OPS NULL -#endif - -static struct platform_driver mcfqspi_driver = { - .driver.name = DRIVER_NAME, - .driver.owner = THIS_MODULE, - .driver.pm = MCFQSPI_DEV_PM_OPS, - .remove = __devexit_p(mcfqspi_remove), -}; - -static int __init mcfqspi_init(void) -{ - return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe); -} -module_init(mcfqspi_init); - -static void __exit mcfqspi_exit(void) -{ - platform_driver_unregister(&mcfqspi_driver); -} -module_exit(mcfqspi_exit); - -MODULE_AUTHOR("Steven King "); -MODULE_DESCRIPTION("Coldfire QSPI Controller Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/trunk/drivers/spi/davinci_spi.c b/trunk/drivers/spi/davinci_spi.c deleted file mode 100644 index 225ab60b02c4..000000000000 --- a/trunk/drivers/spi/davinci_spi.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (C) 2009 Texas Instruments. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define SPI_NO_RESOURCE ((resource_size_t)-1) - -#define SPI_MAX_CHIPSELECT 2 - -#define CS_DEFAULT 0xFF - -#define SPI_BUFSIZ (SMP_CACHE_BYTES + 1) -#define DAVINCI_DMA_DATA_TYPE_S8 0x01 -#define DAVINCI_DMA_DATA_TYPE_S16 0x02 -#define DAVINCI_DMA_DATA_TYPE_S32 0x04 - -#define SPIFMT_PHASE_MASK BIT(16) -#define SPIFMT_POLARITY_MASK BIT(17) -#define SPIFMT_DISTIMER_MASK BIT(18) -#define SPIFMT_SHIFTDIR_MASK BIT(20) -#define SPIFMT_WAITENA_MASK BIT(21) -#define SPIFMT_PARITYENA_MASK BIT(22) -#define SPIFMT_ODD_PARITY_MASK BIT(23) -#define SPIFMT_WDELAY_MASK 0x3f000000u -#define SPIFMT_WDELAY_SHIFT 24 -#define SPIFMT_CHARLEN_MASK 0x0000001Fu - -/* SPIGCR1 */ -#define SPIGCR1_SPIENA_MASK 0x01000000u - -/* SPIPC0 */ -#define SPIPC0_DIFUN_MASK BIT(11) /* MISO */ -#define SPIPC0_DOFUN_MASK BIT(10) /* MOSI */ -#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */ -#define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */ -#define SPIPC0_EN1FUN_MASK BIT(1) -#define SPIPC0_EN0FUN_MASK BIT(0) - -#define SPIINT_MASKALL 0x0101035F -#define SPI_INTLVL_1 0x000001FFu -#define SPI_INTLVL_0 0x00000000u - -/* SPIDAT1 */ -#define SPIDAT1_CSHOLD_SHIFT 28 -#define SPIDAT1_CSNR_SHIFT 16 -#define SPIGCR1_CLKMOD_MASK BIT(1) -#define SPIGCR1_MASTER_MASK BIT(0) -#define SPIGCR1_LOOPBACK_MASK BIT(16) - -/* SPIBUF */ -#define SPIBUF_TXFULL_MASK BIT(29) -#define SPIBUF_RXEMPTY_MASK BIT(31) - -/* Error Masks */ -#define SPIFLG_DLEN_ERR_MASK BIT(0) -#define SPIFLG_TIMEOUT_MASK BIT(1) -#define SPIFLG_PARERR_MASK BIT(2) -#define SPIFLG_DESYNC_MASK BIT(3) -#define SPIFLG_BITERR_MASK BIT(4) -#define SPIFLG_OVRRUN_MASK BIT(6) -#define SPIFLG_RX_INTR_MASK BIT(8) -#define SPIFLG_TX_INTR_MASK BIT(9) -#define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24) -#define SPIFLG_MASK (SPIFLG_DLEN_ERR_MASK \ - | SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \ - | SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \ - | SPIFLG_OVRRUN_MASK | SPIFLG_RX_INTR_MASK \ - | SPIFLG_TX_INTR_MASK \ - | SPIFLG_BUF_INIT_ACTIVE_MASK) - -#define SPIINT_DLEN_ERR_INTR BIT(0) -#define SPIINT_TIMEOUT_INTR BIT(1) -#define SPIINT_PARERR_INTR BIT(2) -#define SPIINT_DESYNC_INTR BIT(3) -#define SPIINT_BITERR_INTR BIT(4) -#define SPIINT_OVRRUN_INTR BIT(6) -#define SPIINT_RX_INTR BIT(8) -#define SPIINT_TX_INTR BIT(9) -#define SPIINT_DMA_REQ_EN BIT(16) -#define SPIINT_ENABLE_HIGHZ BIT(24) - -#define SPI_T2CDELAY_SHIFT 16 -#define SPI_C2TDELAY_SHIFT 24 - -/* SPI Controller registers */ -#define SPIGCR0 0x00 -#define SPIGCR1 0x04 -#define SPIINT 0x08 -#define SPILVL 0x0c -#define SPIFLG 0x10 -#define SPIPC0 0x14 -#define SPIPC1 0x18 -#define SPIPC2 0x1c -#define SPIPC3 0x20 -#define SPIPC4 0x24 -#define SPIPC5 0x28 -#define SPIPC6 0x2c -#define SPIPC7 0x30 -#define SPIPC8 0x34 -#define SPIDAT0 0x38 -#define SPIDAT1 0x3c -#define SPIBUF 0x40 -#define SPIEMU 0x44 -#define SPIDELAY 0x48 -#define SPIDEF 0x4c -#define SPIFMT0 0x50 -#define SPIFMT1 0x54 -#define SPIFMT2 0x58 -#define SPIFMT3 0x5c -#define TGINTVEC0 0x60 -#define TGINTVEC1 0x64 - -struct davinci_spi_slave { - u32 cmd_to_write; - u32 clk_ctrl_to_write; - u32 bytes_per_word; - u8 active_cs; -}; - -/* We have 2 DMA channels per CS, one for RX and one for TX */ -struct davinci_spi_dma { - int dma_tx_channel; - int dma_rx_channel; - int dma_tx_sync_dev; - int dma_rx_sync_dev; - enum dma_event_q eventq; - - struct completion dma_tx_completion; - struct completion dma_rx_completion; -}; - -/* SPI Controller driver's private data. */ -struct davinci_spi { - struct spi_bitbang bitbang; - struct clk *clk; - - u8 version; - resource_size_t pbase; - void __iomem *base; - size_t region_size; - u32 irq; - struct completion done; - - const void *tx; - void *rx; - u8 *tmp_buf; - int count; - struct davinci_spi_dma *dma_channels; - struct davinci_spi_platform_data *pdata; - - void (*get_rx)(u32 rx_data, struct davinci_spi *); - u32 (*get_tx)(struct davinci_spi *); - - struct davinci_spi_slave slave[SPI_MAX_CHIPSELECT]; -}; - -static unsigned use_dma; - -static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi) -{ - u8 *rx = davinci_spi->rx; - - *rx++ = (u8)data; - davinci_spi->rx = rx; -} - -static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *davinci_spi) -{ - u16 *rx = davinci_spi->rx; - - *rx++ = (u16)data; - davinci_spi->rx = rx; -} - -static u32 davinci_spi_tx_buf_u8(struct davinci_spi *davinci_spi) -{ - u32 data; - const u8 *tx = davinci_spi->tx; - - data = *tx++; - davinci_spi->tx = tx; - return data; -} - -static u32 davinci_spi_tx_buf_u16(struct davinci_spi *davinci_spi) -{ - u32 data; - const u16 *tx = davinci_spi->tx; - - data = *tx++; - davinci_spi->tx = tx; - return data; -} - -static inline void set_io_bits(void __iomem *addr, u32 bits) -{ - u32 v = ioread32(addr); - - v |= bits; - iowrite32(v, addr); -} - -static inline void clear_io_bits(void __iomem *addr, u32 bits) -{ - u32 v = ioread32(addr); - - v &= ~bits; - iowrite32(v, addr); -} - -static inline void set_fmt_bits(void __iomem *addr, u32 bits, int cs_num) -{ - set_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits); -} - -static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int cs_num) -{ - clear_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits); -} - -static void davinci_spi_set_dma_req(const struct spi_device *spi, int enable) -{ - struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master); - - if (enable) - set_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN); - else - clear_io_bits(davinci_spi->base + SPIINT, SPIINT_DMA_REQ_EN); -} - -/* - * Interface to control the chip select signal - */ -static void davinci_spi_chipselect(struct spi_device *spi, int value) -{ - struct davinci_spi *davinci_spi; - struct davinci_spi_platform_data *pdata; - u32 data1_reg_val = 0; - - davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; - - /* - * Board specific chip select logic decides the polarity and cs - * line for the controller - */ - if (value == BITBANG_CS_INACTIVE) { - set_io_bits(davinci_spi->base + SPIDEF, CS_DEFAULT); - - data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT; - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); - - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); - } -} - -/** - * davinci_spi_setup_transfer - This functions will determine transfer method - * @spi: spi device on which data transfer to be done - * @t: spi transfer in which transfer info is filled - * - * This function determines data transfer method (8/16/32 bit transfer). - * It will also set the SPI Clock Control register according to - * SPI slave device freq. - */ -static int davinci_spi_setup_transfer(struct spi_device *spi, - struct spi_transfer *t) -{ - - struct davinci_spi *davinci_spi; - struct davinci_spi_platform_data *pdata; - u8 bits_per_word = 0; - u32 hz = 0, prescale; - - davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; - - if (t) { - bits_per_word = t->bits_per_word; - hz = t->speed_hz; - } - - /* if bits_per_word is not set then set it default */ - if (!bits_per_word) - bits_per_word = spi->bits_per_word; - - /* - * Assign function pointer to appropriate transfer method - * 8bit, 16bit or 32bit transfer - */ - if (bits_per_word <= 8 && bits_per_word >= 2) { - davinci_spi->get_rx = davinci_spi_rx_buf_u8; - davinci_spi->get_tx = davinci_spi_tx_buf_u8; - davinci_spi->slave[spi->chip_select].bytes_per_word = 1; - } else if (bits_per_word <= 16 && bits_per_word >= 2) { - davinci_spi->get_rx = davinci_spi_rx_buf_u16; - davinci_spi->get_tx = davinci_spi_tx_buf_u16; - davinci_spi->slave[spi->chip_select].bytes_per_word = 2; - } else - return -EINVAL; - - if (!hz) - hz = spi->max_speed_hz; - - clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK, - spi->chip_select); - set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f, - spi->chip_select); - - prescale = ((clk_get_rate(davinci_spi->clk) / hz) - 1) & 0xff; - - clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select); - set_fmt_bits(davinci_spi->base, prescale << 8, spi->chip_select); - - return 0; -} - -static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data) -{ - struct spi_device *spi = (struct spi_device *)data; - struct davinci_spi *davinci_spi; - struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; - - davinci_spi = spi_master_get_devdata(spi->master); - davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]); - pdata = davinci_spi->pdata; - - if (ch_status == DMA_COMPLETE) - edma_stop(davinci_spi_dma->dma_rx_channel); - else - edma_clean_channel(davinci_spi_dma->dma_rx_channel); - - complete(&davinci_spi_dma->dma_rx_completion); - /* We must disable the DMA RX request */ - davinci_spi_set_dma_req(spi, 0); -} - -static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data) -{ - struct spi_device *spi = (struct spi_device *)data; - struct davinci_spi *davinci_spi; - struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; - - davinci_spi = spi_master_get_devdata(spi->master); - davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]); - pdata = davinci_spi->pdata; - - if (ch_status == DMA_COMPLETE) - edma_stop(davinci_spi_dma->dma_tx_channel); - else - edma_clean_channel(davinci_spi_dma->dma_tx_channel); - - complete(&davinci_spi_dma->dma_tx_completion); - /* We must disable the DMA TX request */ - davinci_spi_set_dma_req(spi, 0); -} - -static int davinci_spi_request_dma(struct spi_device *spi) -{ - struct davinci_spi *davinci_spi; - struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; - struct device *sdev; - int r; - - davinci_spi = spi_master_get_devdata(spi->master); - davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - pdata = davinci_spi->pdata; - sdev = davinci_spi->bitbang.master->dev.parent; - - r = edma_alloc_channel(davinci_spi_dma->dma_rx_sync_dev, - davinci_spi_dma_rx_callback, spi, - davinci_spi_dma->eventq); - if (r < 0) { - dev_dbg(sdev, "Unable to request DMA channel for SPI RX\n"); - return -EAGAIN; - } - davinci_spi_dma->dma_rx_channel = r; - r = edma_alloc_channel(davinci_spi_dma->dma_tx_sync_dev, - davinci_spi_dma_tx_callback, spi, - davinci_spi_dma->eventq); - if (r < 0) { - edma_free_channel(davinci_spi_dma->dma_rx_channel); - davinci_spi_dma->dma_rx_channel = -1; - dev_dbg(sdev, "Unable to request DMA channel for SPI TX\n"); - return -EAGAIN; - } - davinci_spi_dma->dma_tx_channel = r; - - return 0; -} - -/** - * davinci_spi_setup - This functions will set default transfer method - * @spi: spi device on which data transfer to be done - * - * This functions sets the default transfer method. - */ - -static int davinci_spi_setup(struct spi_device *spi) -{ - int retval; - struct davinci_spi *davinci_spi; - struct davinci_spi_dma *davinci_spi_dma; - struct device *sdev; - - davinci_spi = spi_master_get_devdata(spi->master); - sdev = davinci_spi->bitbang.master->dev.parent; - - /* if bits per word length is zero then set it default 8 */ - if (!spi->bits_per_word) - spi->bits_per_word = 8; - - davinci_spi->slave[spi->chip_select].cmd_to_write = 0; - - if (use_dma && davinci_spi->dma_channels) { - davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - - if ((davinci_spi_dma->dma_rx_channel == -1) - || (davinci_spi_dma->dma_tx_channel == -1)) { - retval = davinci_spi_request_dma(spi); - if (retval < 0) - return retval; - } - } - - /* - * SPI in DaVinci and DA8xx operate between - * 600 KHz and 50 MHz - */ - if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) { - dev_dbg(sdev, "Operating frequency is not in acceptable " - "range\n"); - return -EINVAL; - } - - /* - * Set up SPIFMTn register, unique to this chipselect. - * - * NOTE: we could do all of these with one write. Also, some - * of the "version 2" features are found in chips that don't - * support all of them... - */ - if (spi->mode & SPI_LSB_FIRST) - set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK, - spi->chip_select); - - if (spi->mode & SPI_CPOL) - set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK, - spi->chip_select); - - if (!(spi->mode & SPI_CPHA)) - set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK, - spi->chip_select); - - /* - * Version 1 hardware supports two basic SPI modes: - * - Standard SPI mode uses 4 pins, with chipselect - * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS) - * (distinct from SPI_3WIRE, with just one data wire; - * or similar variants without MOSI or without MISO) - * - * Version 2 hardware supports an optional handshaking signal, - * so it can support two more modes: - * - 5 pin SPI variant is standard SPI plus SPI_READY - * - 4 pin with enable is (SPI_READY | SPI_NO_CS) - */ - - if (davinci_spi->version == SPI_VERSION_2) { - clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK, - spi->chip_select); - set_fmt_bits(davinci_spi->base, - (davinci_spi->pdata->wdelay - << SPIFMT_WDELAY_SHIFT) - & SPIFMT_WDELAY_MASK, - spi->chip_select); - - if (davinci_spi->pdata->odd_parity) - set_fmt_bits(davinci_spi->base, - SPIFMT_ODD_PARITY_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_ODD_PARITY_MASK, - spi->chip_select); - - if (davinci_spi->pdata->parity_enable) - set_fmt_bits(davinci_spi->base, - SPIFMT_PARITYENA_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_PARITYENA_MASK, - spi->chip_select); - - if (davinci_spi->pdata->wait_enable) - set_fmt_bits(davinci_spi->base, - SPIFMT_WAITENA_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_WAITENA_MASK, - spi->chip_select); - - if (davinci_spi->pdata->timer_disable) - set_fmt_bits(davinci_spi->base, - SPIFMT_DISTIMER_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_DISTIMER_MASK, - spi->chip_select); - } - - retval = davinci_spi_setup_transfer(spi, NULL); - - return retval; -} - -static void davinci_spi_cleanup(struct spi_device *spi) -{ - struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master); - struct davinci_spi_dma *davinci_spi_dma; - - davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - - if (use_dma && davinci_spi->dma_channels) { - davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - - if ((davinci_spi_dma->dma_rx_channel != -1) - && (davinci_spi_dma->dma_tx_channel != -1)) { - edma_free_channel(davinci_spi_dma->dma_tx_channel); - edma_free_channel(davinci_spi_dma->dma_rx_channel); - } - } -} - -static int davinci_spi_bufs_prep(struct spi_device *spi, - struct davinci_spi *davinci_spi) -{ - int op_mode = 0; - - /* - * REVISIT unless devices disagree about SPI_LOOP or - * SPI_READY (SPI_NO_CS only allows one device!), this - * should not need to be done before each message... - * optimize for both flags staying cleared. - */ - - op_mode = SPIPC0_DIFUN_MASK - | SPIPC0_DOFUN_MASK - | SPIPC0_CLKFUN_MASK; - if (!(spi->mode & SPI_NO_CS)) - op_mode |= 1 << spi->chip_select; - if (spi->mode & SPI_READY) - op_mode |= SPIPC0_SPIENA_MASK; - - iowrite32(op_mode, davinci_spi->base + SPIPC0); - - if (spi->mode & SPI_LOOP) - set_io_bits(davinci_spi->base + SPIGCR1, - SPIGCR1_LOOPBACK_MASK); - else - clear_io_bits(davinci_spi->base + SPIGCR1, - SPIGCR1_LOOPBACK_MASK); - - return 0; -} - -static int davinci_spi_check_error(struct davinci_spi *davinci_spi, - int int_status) -{ - struct device *sdev = davinci_spi->bitbang.master->dev.parent; - - if (int_status & SPIFLG_TIMEOUT_MASK) { - dev_dbg(sdev, "SPI Time-out Error\n"); - return -ETIMEDOUT; - } - if (int_status & SPIFLG_DESYNC_MASK) { - dev_dbg(sdev, "SPI Desynchronization Error\n"); - return -EIO; - } - if (int_status & SPIFLG_BITERR_MASK) { - dev_dbg(sdev, "SPI Bit error\n"); - return -EIO; - } - - if (davinci_spi->version == SPI_VERSION_2) { - if (int_status & SPIFLG_DLEN_ERR_MASK) { - dev_dbg(sdev, "SPI Data Length Error\n"); - return -EIO; - } - if (int_status & SPIFLG_PARERR_MASK) { - dev_dbg(sdev, "SPI Parity Error\n"); - return -EIO; - } - if (int_status & SPIFLG_OVRRUN_MASK) { - dev_dbg(sdev, "SPI Data Overrun error\n"); - return -EIO; - } - if (int_status & SPIFLG_TX_INTR_MASK) { - dev_dbg(sdev, "SPI TX intr bit set\n"); - return -EIO; - } - if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) { - dev_dbg(sdev, "SPI Buffer Init Active\n"); - return -EBUSY; - } - } - - return 0; -} - -/** - * davinci_spi_bufs - functions which will handle transfer data - * @spi: spi device on which data transfer to be done - * @t: spi transfer in which transfer info is filled - * - * This function will put data to be transferred into data register - * of SPI controller and then wait until the completion will be marked - * by the IRQ Handler. - */ -static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) -{ - struct davinci_spi *davinci_spi; - int int_status, count, ret; - u8 conv, tmp; - u32 tx_data, data1_reg_val; - u32 buf_val, flg_val; - struct davinci_spi_platform_data *pdata; - - davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; - - davinci_spi->tx = t->tx_buf; - davinci_spi->rx = t->rx_buf; - - /* convert len to words based on bits_per_word */ - conv = davinci_spi->slave[spi->chip_select].bytes_per_word; - davinci_spi->count = t->len / conv; - - INIT_COMPLETION(davinci_spi->done); - - ret = davinci_spi_bufs_prep(spi, davinci_spi); - if (ret) - return ret; - - /* Enable SPI */ - set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - - iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) | - (pdata->t2cdelay << SPI_T2CDELAY_SHIFT), - davinci_spi->base + SPIDELAY); - - count = davinci_spi->count; - data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT; - tmp = ~(0x1 << spi->chip_select); - - clear_io_bits(davinci_spi->base + SPIDEF, ~tmp); - - data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT; - - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); - - /* Determine the command to execute READ or WRITE */ - if (t->tx_buf) { - clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); - - while (1) { - tx_data = davinci_spi->get_tx(davinci_spi); - - data1_reg_val &= ~(0xFFFF); - data1_reg_val |= (0xFFFF & tx_data); - - buf_val = ioread32(davinci_spi->base + SPIBUF); - if ((buf_val & SPIBUF_TXFULL_MASK) == 0) { - iowrite32(data1_reg_val, - davinci_spi->base + SPIDAT1); - - count--; - } - while (ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) - cpu_relax(); - - /* getting the returned byte */ - if (t->rx_buf) { - buf_val = ioread32(davinci_spi->base + SPIBUF); - davinci_spi->get_rx(buf_val, davinci_spi); - } - if (count <= 0) - break; - } - } else { - if (pdata->poll_mode) { - while (1) { - /* keeps the serial clock going */ - if ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_TXFULL_MASK) == 0) - iowrite32(data1_reg_val, - davinci_spi->base + SPIDAT1); - - while (ioread32(davinci_spi->base + SPIBUF) & - SPIBUF_RXEMPTY_MASK) - cpu_relax(); - - flg_val = ioread32(davinci_spi->base + SPIFLG); - buf_val = ioread32(davinci_spi->base + SPIBUF); - - davinci_spi->get_rx(buf_val, davinci_spi); - - count--; - if (count <= 0) - break; - } - } else { /* Receive in Interrupt mode */ - int i; - - for (i = 0; i < davinci_spi->count; i++) { - set_io_bits(davinci_spi->base + SPIINT, - SPIINT_BITERR_INTR - | SPIINT_OVRRUN_INTR - | SPIINT_RX_INTR); - - iowrite32(data1_reg_val, - davinci_spi->base + SPIDAT1); - - while (ioread32(davinci_spi->base + SPIINT) & - SPIINT_RX_INTR) - cpu_relax(); - } - iowrite32((data1_reg_val & 0x0ffcffff), - davinci_spi->base + SPIDAT1); - } - } - - /* - * Check for bit error, desync error,parity error,timeout error and - * receive overflow errors - */ - int_status = ioread32(davinci_spi->base + SPIFLG); - - ret = davinci_spi_check_error(davinci_spi, int_status); - if (ret != 0) - return ret; - - /* SPI Framework maintains the count only in bytes so convert back */ - davinci_spi->count *= conv; - - return t->len; -} - -#define DAVINCI_DMA_DATA_TYPE_S8 0x01 -#define DAVINCI_DMA_DATA_TYPE_S16 0x02 -#define DAVINCI_DMA_DATA_TYPE_S32 0x04 - -static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) -{ - struct davinci_spi *davinci_spi; - int int_status = 0; - int count, temp_count; - u8 conv = 1; - u8 tmp; - u32 data1_reg_val; - struct davinci_spi_dma *davinci_spi_dma; - int word_len, data_type, ret; - unsigned long tx_reg, rx_reg; - struct davinci_spi_platform_data *pdata; - struct device *sdev; - - davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; - sdev = davinci_spi->bitbang.master->dev.parent; - - davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - - tx_reg = (unsigned long)davinci_spi->pbase + SPIDAT1; - rx_reg = (unsigned long)davinci_spi->pbase + SPIBUF; - - davinci_spi->tx = t->tx_buf; - davinci_spi->rx = t->rx_buf; - - /* convert len to words based on bits_per_word */ - conv = davinci_spi->slave[spi->chip_select].bytes_per_word; - davinci_spi->count = t->len / conv; - - INIT_COMPLETION(davinci_spi->done); - - init_completion(&davinci_spi_dma->dma_rx_completion); - init_completion(&davinci_spi_dma->dma_tx_completion); - - word_len = conv * 8; - - if (word_len <= 8) - data_type = DAVINCI_DMA_DATA_TYPE_S8; - else if (word_len <= 16) - data_type = DAVINCI_DMA_DATA_TYPE_S16; - else if (word_len <= 32) - data_type = DAVINCI_DMA_DATA_TYPE_S32; - else - return -EINVAL; - - ret = davinci_spi_bufs_prep(spi, davinci_spi); - if (ret) - return ret; - - /* Put delay val if required */ - iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) | - (pdata->t2cdelay << SPI_T2CDELAY_SHIFT), - davinci_spi->base + SPIDELAY); - - count = davinci_spi->count; /* the number of elements */ - data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT; - - /* CS default = 0xFF */ - tmp = ~(0x1 << spi->chip_select); - - clear_io_bits(davinci_spi->base + SPIDEF, ~tmp); - - data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT; - - /* disable all interrupts for dma transfers */ - clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); - /* Disable SPI to write configuration bits in SPIDAT */ - clear_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); - /* Enable SPI */ - set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); - - - if (t->tx_buf) { - t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, count, - DMA_TO_DEVICE); - if (dma_mapping_error(&spi->dev, t->tx_dma)) { - dev_dbg(sdev, "Unable to DMA map a %d bytes" - " TX buffer\n", count); - return -ENOMEM; - } - temp_count = count; - } else { - /* We need TX clocking for RX transaction */ - t->tx_dma = dma_map_single(&spi->dev, - (void *)davinci_spi->tmp_buf, count + 1, - DMA_TO_DEVICE); - if (dma_mapping_error(&spi->dev, t->tx_dma)) { - dev_dbg(sdev, "Unable to DMA map a %d bytes" - " TX tmp buffer\n", count); - return -ENOMEM; - } - temp_count = count + 1; - } - - edma_set_transfer_params(davinci_spi_dma->dma_tx_channel, - data_type, temp_count, 1, 0, ASYNC); - edma_set_dest(davinci_spi_dma->dma_tx_channel, tx_reg, INCR, W8BIT); - edma_set_src(davinci_spi_dma->dma_tx_channel, t->tx_dma, INCR, W8BIT); - edma_set_src_index(davinci_spi_dma->dma_tx_channel, data_type, 0); - edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0); - - if (t->rx_buf) { - /* initiate transaction */ - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); - - t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count, - DMA_FROM_DEVICE); - if (dma_mapping_error(&spi->dev, t->rx_dma)) { - dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", - count); - if (t->tx_buf != NULL) - dma_unmap_single(NULL, t->tx_dma, - count, DMA_TO_DEVICE); - return -ENOMEM; - } - edma_set_transfer_params(davinci_spi_dma->dma_rx_channel, - data_type, count, 1, 0, ASYNC); - edma_set_src(davinci_spi_dma->dma_rx_channel, - rx_reg, INCR, W8BIT); - edma_set_dest(davinci_spi_dma->dma_rx_channel, - t->rx_dma, INCR, W8BIT); - edma_set_src_index(davinci_spi_dma->dma_rx_channel, 0, 0); - edma_set_dest_index(davinci_spi_dma->dma_rx_channel, - data_type, 0); - } - - if ((t->tx_buf) || (t->rx_buf)) - edma_start(davinci_spi_dma->dma_tx_channel); - - if (t->rx_buf) - edma_start(davinci_spi_dma->dma_rx_channel); - - if ((t->rx_buf) || (t->tx_buf)) - davinci_spi_set_dma_req(spi, 1); - - if (t->tx_buf) - wait_for_completion_interruptible( - &davinci_spi_dma->dma_tx_completion); - - if (t->rx_buf) - wait_for_completion_interruptible( - &davinci_spi_dma->dma_rx_completion); - - dma_unmap_single(NULL, t->tx_dma, temp_count, DMA_TO_DEVICE); - - if (t->rx_buf) - dma_unmap_single(NULL, t->rx_dma, count, DMA_FROM_DEVICE); - - /* - * Check for bit error, desync error,parity error,timeout error and - * receive overflow errors - */ - int_status = ioread32(davinci_spi->base + SPIFLG); - - ret = davinci_spi_check_error(davinci_spi, int_status); - if (ret != 0) - return ret; - - /* SPI Framework maintains the count only in bytes so convert back */ - davinci_spi->count *= conv; - - return t->len; -} - -/** - * davinci_spi_irq - IRQ handler for DaVinci SPI - * @irq: IRQ number for this SPI Master - * @context_data: structure for SPI Master controller davinci_spi - */ -static irqreturn_t davinci_spi_irq(s32 irq, void *context_data) -{ - struct davinci_spi *davinci_spi = context_data; - u32 int_status, rx_data = 0; - irqreturn_t ret = IRQ_NONE; - - int_status = ioread32(davinci_spi->base + SPIFLG); - - while ((int_status & SPIFLG_RX_INTR_MASK)) { - if (likely(int_status & SPIFLG_RX_INTR_MASK)) { - ret = IRQ_HANDLED; - - rx_data = ioread32(davinci_spi->base + SPIBUF); - davinci_spi->get_rx(rx_data, davinci_spi); - - /* Disable Receive Interrupt */ - iowrite32(~(SPIINT_RX_INTR | SPIINT_TX_INTR), - davinci_spi->base + SPIINT); - } else - (void)davinci_spi_check_error(davinci_spi, int_status); - - int_status = ioread32(davinci_spi->base + SPIFLG); - } - - return ret; -} - -/** - * davinci_spi_probe - probe function for SPI Master Controller - * @pdev: platform_device structure which contains plateform specific data - */ -static int davinci_spi_probe(struct platform_device *pdev) -{ - struct spi_master *master; - struct davinci_spi *davinci_spi; - struct davinci_spi_platform_data *pdata; - struct resource *r, *mem; - resource_size_t dma_rx_chan = SPI_NO_RESOURCE; - resource_size_t dma_tx_chan = SPI_NO_RESOURCE; - resource_size_t dma_eventq = SPI_NO_RESOURCE; - int i = 0, ret = 0; - - pdata = pdev->dev.platform_data; - if (pdata == NULL) { - ret = -ENODEV; - goto err; - } - - master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); - if (master == NULL) { - ret = -ENOMEM; - goto err; - } - - dev_set_drvdata(&pdev->dev, master); - - davinci_spi = spi_master_get_devdata(master); - if (davinci_spi == NULL) { - ret = -ENOENT; - goto free_master; - } - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - ret = -ENOENT; - goto free_master; - } - - davinci_spi->pbase = r->start; - davinci_spi->region_size = resource_size(r); - davinci_spi->pdata = pdata; - - mem = request_mem_region(r->start, davinci_spi->region_size, - pdev->name); - if (mem == NULL) { - ret = -EBUSY; - goto free_master; - } - - davinci_spi->base = (struct davinci_spi_reg __iomem *) - ioremap(r->start, davinci_spi->region_size); - if (davinci_spi->base == NULL) { - ret = -ENOMEM; - goto release_region; - } - - davinci_spi->irq = platform_get_irq(pdev, 0); - if (davinci_spi->irq <= 0) { - ret = -EINVAL; - goto unmap_io; - } - - ret = request_irq(davinci_spi->irq, davinci_spi_irq, IRQF_DISABLED, - dev_name(&pdev->dev), davinci_spi); - if (ret) - goto unmap_io; - - /* Allocate tmp_buf for tx_buf */ - davinci_spi->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL); - if (davinci_spi->tmp_buf == NULL) { - ret = -ENOMEM; - goto irq_free; - } - - davinci_spi->bitbang.master = spi_master_get(master); - if (davinci_spi->bitbang.master == NULL) { - ret = -ENODEV; - goto free_tmp_buf; - } - - davinci_spi->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(davinci_spi->clk)) { - ret = -ENODEV; - goto put_master; - } - clk_enable(davinci_spi->clk); - - - master->bus_num = pdev->id; - master->num_chipselect = pdata->num_chipselect; - master->setup = davinci_spi_setup; - master->cleanup = davinci_spi_cleanup; - - davinci_spi->bitbang.chipselect = davinci_spi_chipselect; - davinci_spi->bitbang.setup_transfer = davinci_spi_setup_transfer; - - davinci_spi->version = pdata->version; - use_dma = pdata->use_dma; - - davinci_spi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; - if (davinci_spi->version == SPI_VERSION_2) - davinci_spi->bitbang.flags |= SPI_READY; - - if (use_dma) { - r = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (r) - dma_rx_chan = r->start; - r = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (r) - dma_tx_chan = r->start; - r = platform_get_resource(pdev, IORESOURCE_DMA, 2); - if (r) - dma_eventq = r->start; - } - - if (!use_dma || - dma_rx_chan == SPI_NO_RESOURCE || - dma_tx_chan == SPI_NO_RESOURCE || - dma_eventq == SPI_NO_RESOURCE) { - davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio; - use_dma = 0; - } else { - davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_dma; - davinci_spi->dma_channels = kzalloc(master->num_chipselect - * sizeof(struct davinci_spi_dma), GFP_KERNEL); - if (davinci_spi->dma_channels == NULL) { - ret = -ENOMEM; - goto free_clk; - } - - for (i = 0; i < master->num_chipselect; i++) { - davinci_spi->dma_channels[i].dma_rx_channel = -1; - davinci_spi->dma_channels[i].dma_rx_sync_dev = - dma_rx_chan; - davinci_spi->dma_channels[i].dma_tx_channel = -1; - davinci_spi->dma_channels[i].dma_tx_sync_dev = - dma_tx_chan; - davinci_spi->dma_channels[i].eventq = dma_eventq; - } - dev_info(&pdev->dev, "DaVinci SPI driver in EDMA mode\n" - "Using RX channel = %d , TX channel = %d and " - "event queue = %d", dma_rx_chan, dma_tx_chan, - dma_eventq); - } - - davinci_spi->get_rx = davinci_spi_rx_buf_u8; - davinci_spi->get_tx = davinci_spi_tx_buf_u8; - - init_completion(&davinci_spi->done); - - /* Reset In/OUT SPI module */ - iowrite32(0, davinci_spi->base + SPIGCR0); - udelay(100); - iowrite32(1, davinci_spi->base + SPIGCR0); - - /* Clock internal */ - if (davinci_spi->pdata->clk_internal) - set_io_bits(davinci_spi->base + SPIGCR1, - SPIGCR1_CLKMOD_MASK); - else - clear_io_bits(davinci_spi->base + SPIGCR1, - SPIGCR1_CLKMOD_MASK); - - /* master mode default */ - set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK); - - if (davinci_spi->pdata->intr_level) - iowrite32(SPI_INTLVL_1, davinci_spi->base + SPILVL); - else - iowrite32(SPI_INTLVL_0, davinci_spi->base + SPILVL); - - ret = spi_bitbang_start(&davinci_spi->bitbang); - if (ret) - goto free_clk; - - dev_info(&pdev->dev, "Controller at 0x%p \n", davinci_spi->base); - - if (!pdata->poll_mode) - dev_info(&pdev->dev, "Operating in interrupt mode" - " using IRQ %d\n", davinci_spi->irq); - - return ret; - -free_clk: - clk_disable(davinci_spi->clk); - clk_put(davinci_spi->clk); -put_master: - spi_master_put(master); -free_tmp_buf: - kfree(davinci_spi->tmp_buf); -irq_free: - free_irq(davinci_spi->irq, davinci_spi); -unmap_io: - iounmap(davinci_spi->base); -release_region: - release_mem_region(davinci_spi->pbase, davinci_spi->region_size); -free_master: - kfree(master); -err: - return ret; -} - -/** - * davinci_spi_remove - remove function for SPI Master Controller - * @pdev: platform_device structure which contains plateform specific data - * - * This function will do the reverse action of davinci_spi_probe function - * It will free the IRQ and SPI controller's memory region. - * It will also call spi_bitbang_stop to destroy the work queue which was - * created by spi_bitbang_start. - */ -static int __exit davinci_spi_remove(struct platform_device *pdev) -{ - struct davinci_spi *davinci_spi; - struct spi_master *master; - - master = dev_get_drvdata(&pdev->dev); - davinci_spi = spi_master_get_devdata(master); - - spi_bitbang_stop(&davinci_spi->bitbang); - - clk_disable(davinci_spi->clk); - clk_put(davinci_spi->clk); - spi_master_put(master); - kfree(davinci_spi->tmp_buf); - free_irq(davinci_spi->irq, davinci_spi); - iounmap(davinci_spi->base); - release_mem_region(davinci_spi->pbase, davinci_spi->region_size); - - return 0; -} - -static struct platform_driver davinci_spi_driver = { - .driver.name = "spi_davinci", - .remove = __exit_p(davinci_spi_remove), -}; - -static int __init davinci_spi_init(void) -{ - return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe); -} -module_init(davinci_spi_init); - -static void __exit davinci_spi_exit(void) -{ - platform_driver_unregister(&davinci_spi_driver); -} -module_exit(davinci_spi_exit); - -MODULE_DESCRIPTION("TI DaVinci SPI Master Controller Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/spi/dw_spi.c b/trunk/drivers/spi/dw_spi.c index 8ed38f1d6c18..31620fae77be 100644 --- a/trunk/drivers/spi/dw_spi.c +++ b/trunk/drivers/spi/dw_spi.c @@ -152,7 +152,6 @@ static void mrst_spi_debugfs_remove(struct dw_spi *dws) #else static inline int mrst_spi_debugfs_init(struct dw_spi *dws) { - return 0; } static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) @@ -162,14 +161,14 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) static void wait_till_not_busy(struct dw_spi *dws) { - unsigned long end = jiffies + 1 + usecs_to_jiffies(1000); + unsigned long end = jiffies + usecs_to_jiffies(1000); while (time_before(jiffies, end)) { if (!(dw_readw(dws, sr) & SR_BUSY)) return; } dev_err(&dws->master->dev, - "DW SPI: Status keeps busy for 1000us after a read/write!\n"); + "DW SPI: Stutus keeps busy for 1000us after a read/write!\n"); } static void flush(struct dw_spi *dws) @@ -359,8 +358,6 @@ static void transfer_complete(struct dw_spi *dws) static irqreturn_t interrupt_transfer(struct dw_spi *dws) { u16 irq_status, irq_mask = 0x3f; - u32 int_level = dws->fifo_len / 2; - u32 left; irq_status = dw_readw(dws, isr) & irq_mask; /* Error handling */ @@ -372,23 +369,22 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) return IRQ_HANDLED; } - if (irq_status & SPI_INT_TXEI) { - spi_mask_intr(dws, SPI_INT_TXEI); - - left = (dws->tx_end - dws->tx) / dws->n_bytes; - left = (left > int_level) ? int_level : left; - - while (left--) + /* INT comes from tx */ + if (dws->tx && (irq_status & SPI_INT_TXEI)) { + while (dws->tx < dws->tx_end) dws->write(dws); - dws->read(dws); - /* Re-enable the IRQ if there is still data left to tx */ - if (dws->tx_end > dws->tx) - spi_umask_intr(dws, SPI_INT_TXEI); - else + if (dws->tx == dws->tx_end) { + spi_mask_intr(dws, SPI_INT_TXEI); transfer_complete(dws); + } } + /* INT comes from rx */ + if (dws->rx && (irq_status & SPI_INT_RXFI)) { + if (dws->read(dws)) + transfer_complete(dws); + } return IRQ_HANDLED; } @@ -408,9 +404,12 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id) /* Must be called inside pump_transfers() */ static void poll_transfer(struct dw_spi *dws) { - while (dws->write(dws)) - dws->read(dws); + if (dws->tx) { + while (dws->write(dws)) + dws->read(dws); + } + dws->read(dws); transfer_complete(dws); } @@ -429,7 +428,6 @@ static void pump_transfers(unsigned long data) u8 bits = 0; u8 imask = 0; u8 cs_change = 0; - u16 txint_level = 0; u16 clk_div = 0; u32 speed = 0; u32 cr0 = 0; @@ -440,9 +438,6 @@ static void pump_transfers(unsigned long data) chip = dws->cur_chip; spi = message->spi; - if (unlikely(!chip->clk_div)) - chip->clk_div = dws->max_freq / chip->speed_hz; - if (message->state == ERROR_STATE) { message->status = -EIO; goto early_exit; @@ -497,7 +492,7 @@ static void pump_transfers(unsigned long data) /* clk_div doesn't support odd number */ clk_div = dws->max_freq / speed; - clk_div = (clk_div + 1) & 0xfffe; + clk_div = (clk_div >> 1) << 1; chip->speed_hz = speed; chip->clk_div = clk_div; @@ -537,35 +532,14 @@ static void pump_transfers(unsigned long data) } message->state = RUNNING_STATE; - /* - * Adjust transfer mode if necessary. Requires platform dependent - * chipselect mechanism. - */ - if (dws->cs_control) { - if (dws->rx && dws->tx) - chip->tmode = 0x00; - else if (dws->rx) - chip->tmode = 0x02; - else - chip->tmode = 0x01; - - cr0 &= ~(0x3 << SPI_MODE_OFFSET); - cr0 |= (chip->tmode << SPI_TMOD_OFFSET); - } - /* Check if current transfer is a DMA transaction */ dws->dma_mapped = map_dma_buffers(dws); - /* - * Interrupt mode - * we only need set the TXEI IRQ, as TX/RX always happen syncronizely - */ if (!dws->dma_mapped && !chip->poll_mode) { - int templen = dws->len / dws->n_bytes; - txint_level = dws->fifo_len / 2; - txint_level = (templen > txint_level) ? txint_level : templen; - - imask |= SPI_INT_TXEI; + if (dws->rx) + imask |= SPI_INT_RXFI; + if (dws->tx) + imask |= SPI_INT_TXEI; dws->transfer_handler = interrupt_transfer; } @@ -575,23 +549,21 @@ static void pump_transfers(unsigned long data) * 2. clk_div is changed * 3. control value changes */ - if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) { + if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div) { spi_enable_chip(dws, 0); if (dw_readw(dws, ctrl0) != cr0) dw_writew(dws, ctrl0, cr0); - spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); - spi_chip_sel(dws, spi->chip_select); - /* Set the interrupt mask, for poll mode just diable all int */ spi_mask_intr(dws, 0xff); - if (imask) + if (!chip->poll_mode) spi_umask_intr(dws, imask); - if (txint_level) - dw_writew(dws, txfltr, txint_level); + spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); + spi_chip_sel(dws, spi->chip_select); spi_enable_chip(dws, 1); + if (cs_change) dws->prev_chip = chip; } @@ -740,11 +712,11 @@ static int dw_spi_setup(struct spi_device *spi) } chip->bits_per_word = spi->bits_per_word; - if (!spi->max_speed_hz) { - dev_err(&spi->dev, "No max speed HZ parameter\n"); - return -EINVAL; - } chip->speed_hz = spi->max_speed_hz; + if (chip->speed_hz) + chip->clk_div = 25000000 / chip->speed_hz; + else + chip->clk_div = 8; /* default value */ chip->tmode = 0; /* Tx & Rx */ /* Default SPI mode is SCPOL = 0, SCPH = 0 */ @@ -763,7 +735,7 @@ static void dw_spi_cleanup(struct spi_device *spi) kfree(chip); } -static int __devinit init_queue(struct dw_spi *dws) +static int __init init_queue(struct dw_spi *dws) { INIT_LIST_HEAD(&dws->queue); spin_lock_init(&dws->lock); @@ -845,22 +817,6 @@ static void spi_hw_init(struct dw_spi *dws) spi_mask_intr(dws, 0xff); spi_enable_chip(dws, 1); flush(dws); - - /* - * Try to detect the FIFO depth if not set by interface driver, - * the depth could be from 2 to 256 from HW spec - */ - if (!dws->fifo_len) { - u32 fifo; - for (fifo = 2; fifo <= 257; fifo++) { - dw_writew(dws, txfltr, fifo); - if (fifo != dw_readw(dws, txfltr)) - break; - } - - dws->fifo_len = (fifo == 257) ? 0 : fifo; - dw_writew(dws, txfltr, 0); - } } int __devinit dw_spi_add_host(struct dw_spi *dws) @@ -957,7 +913,6 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws) /* Disconnect from the SPI framework */ spi_unregister_master(dws->master); } -EXPORT_SYMBOL(dw_spi_remove_host); int dw_spi_suspend_host(struct dw_spi *dws) { diff --git a/trunk/drivers/spi/dw_spi_mmio.c b/trunk/drivers/spi/dw_spi_mmio.c deleted file mode 100644 index e35b45ac5174..000000000000 --- a/trunk/drivers/spi/dw_spi_mmio.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core - * - * Copyright (c) 2010, Octasic semiconductor. - * - * 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. - */ - -#include -#include -#include -#include -#include - -#define DRIVER_NAME "dw_spi_mmio" - -struct dw_spi_mmio { - struct dw_spi dws; - struct clk *clk; -}; - -static int __devinit dw_spi_mmio_probe(struct platform_device *pdev) -{ - struct dw_spi_mmio *dwsmmio; - struct dw_spi *dws; - struct resource *mem, *ioarea; - int ret; - - dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL); - if (!dwsmmio) { - ret = -ENOMEM; - goto err_end; - } - - dws = &dwsmmio->dws; - - /* Get basic io resource and map it */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - ret = -EINVAL; - goto err_kfree; - } - - ioarea = request_mem_region(mem->start, resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "SPI region already claimed\n"); - ret = -EBUSY; - goto err_kfree; - } - - dws->regs = ioremap_nocache(mem->start, resource_size(mem)); - if (!dws->regs) { - dev_err(&pdev->dev, "SPI region already mapped\n"); - ret = -ENOMEM; - goto err_release_reg; - } - - dws->irq = platform_get_irq(pdev, 0); - if (dws->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); - ret = dws->irq; /* -ENXIO */ - goto err_unmap; - } - - dwsmmio->clk = clk_get(&pdev->dev, NULL); - if (!dwsmmio->clk) { - ret = -ENODEV; - goto err_irq; - } - clk_enable(dwsmmio->clk); - - dws->parent_dev = &pdev->dev; - dws->bus_num = 0; - dws->num_cs = 4; - dws->max_freq = clk_get_rate(dwsmmio->clk); - - ret = dw_spi_add_host(dws); - if (ret) - goto err_clk; - - platform_set_drvdata(pdev, dwsmmio); - return 0; - -err_clk: - clk_disable(dwsmmio->clk); - clk_put(dwsmmio->clk); - dwsmmio->clk = NULL; -err_irq: - free_irq(dws->irq, dws); -err_unmap: - iounmap(dws->regs); -err_release_reg: - release_mem_region(mem->start, resource_size(mem)); -err_kfree: - kfree(dwsmmio); -err_end: - return ret; -} - -static int __devexit dw_spi_mmio_remove(struct platform_device *pdev) -{ - struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); - struct resource *mem; - - platform_set_drvdata(pdev, NULL); - - clk_disable(dwsmmio->clk); - clk_put(dwsmmio->clk); - dwsmmio->clk = NULL; - - free_irq(dwsmmio->dws.irq, &dwsmmio->dws); - dw_spi_remove_host(&dwsmmio->dws); - iounmap(dwsmmio->dws.regs); - kfree(dwsmmio); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - return 0; -} - -static struct platform_driver dw_spi_mmio_driver = { - .remove = __devexit_p(dw_spi_mmio_remove), - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init dw_spi_mmio_init(void) -{ - return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe); -} -module_init(dw_spi_mmio_init); - -static void __exit dw_spi_mmio_exit(void) -{ - platform_driver_unregister(&dw_spi_mmio_driver); -} -module_exit(dw_spi_mmio_exit); - -MODULE_AUTHOR("Jean-Hugues Deschenes "); -MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/spi/dw_spi_pci.c b/trunk/drivers/spi/dw_spi_pci.c index 1f0735f9cc76..34ba69161734 100644 --- a/trunk/drivers/spi/dw_spi_pci.c +++ b/trunk/drivers/spi/dw_spi_pci.c @@ -73,7 +73,6 @@ static int __devinit spi_pci_probe(struct pci_dev *pdev, dws->num_cs = 4; dws->max_freq = 25000000; /* for Moorestwon */ dws->irq = pdev->irq; - dws->fifo_len = 40; /* FIFO has 40 words buffer */ ret = dw_spi_add_host(dws); if (ret) @@ -99,7 +98,6 @@ static void __devexit spi_pci_remove(struct pci_dev *pdev) struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); pci_set_drvdata(pdev, NULL); - dw_spi_remove_host(&dwpci->dws); iounmap(dwpci->dws.regs); pci_release_region(pdev, 0); kfree(dwpci); diff --git a/trunk/drivers/spi/mpc52xx_psc_spi.c b/trunk/drivers/spi/mpc52xx_psc_spi.c index 04747868d6c4..f50c81df336a 100644 --- a/trunk/drivers/spi/mpc52xx_psc_spi.c +++ b/trunk/drivers/spi/mpc52xx_psc_spi.c @@ -503,7 +503,7 @@ static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) return mpc52xx_psc_spi_do_remove(&op->dev); } -static const struct of_device_id mpc52xx_psc_spi_of_match[] = { +static struct of_device_id mpc52xx_psc_spi_of_match[] = { { .compatible = "fsl,mpc5200-psc-spi", }, { .compatible = "mpc5200-psc-spi", }, /* old */ {} diff --git a/trunk/drivers/spi/mpc52xx_spi.c b/trunk/drivers/spi/mpc52xx_spi.c index 6eab46537a0a..45bfe6458173 100644 --- a/trunk/drivers/spi/mpc52xx_spi.c +++ b/trunk/drivers/spi/mpc52xx_spi.c @@ -550,7 +550,7 @@ static int __devexit mpc52xx_spi_remove(struct of_device *op) return 0; } -static const struct of_device_id mpc52xx_spi_match[] __devinitconst = { +static struct of_device_id mpc52xx_spi_match[] __devinitdata = { { .compatible = "fsl,mpc5200-spi", }, {} }; diff --git a/trunk/drivers/spi/spi_imx.c b/trunk/drivers/spi/spi_imx.c index 0ddbbe45e834..1893f1e96dc4 100644 --- a/trunk/drivers/spi/spi_imx.c +++ b/trunk/drivers/spi/spi_imx.c @@ -469,7 +469,7 @@ static int spi_imx_setup(struct spi_device *spi) struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); int gpio = spi_imx->chipselect[spi->chip_select]; - dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__, + pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__, spi->mode, spi->bits_per_word, spi->max_speed_hz); if (gpio >= 0) diff --git a/trunk/drivers/spi/spi_mpc8xxx.c b/trunk/drivers/spi/spi_mpc8xxx.c index 4f0cc9d457e0..1fb2a6ea328c 100644 --- a/trunk/drivers/spi/spi_mpc8xxx.c +++ b/trunk/drivers/spi/spi_mpc8xxx.c @@ -365,7 +365,7 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) if ((mpc8xxx_spi->spibrg / hz) > 64) { cs->hw_mode |= SPMODE_DIV16; - pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1; + pm = mpc8xxx_spi->spibrg / (hz * 64); WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. " "Will use %d Hz instead.\n", dev_name(&spi->dev), @@ -373,7 +373,7 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) if (pm > 16) pm = 16; } else - pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1; + pm = mpc8xxx_spi->spibrg / (hz * 4); if (pm) pm--; @@ -1328,7 +1328,7 @@ static struct of_platform_driver of_mpc8xxx_spi_driver = { static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev) { struct resource *mem; - int irq; + unsigned int irq; struct spi_master *master; if (!pdev->dev.platform_data) @@ -1339,7 +1339,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev) return -EINVAL; irq = platform_get_irq(pdev, 0); - if (irq <= 0) + if (!irq) return -EINVAL; master = mpc8xxx_spi_probe(&pdev->dev, mem, irq); diff --git a/trunk/drivers/spi/spi_ppc4xx.c b/trunk/drivers/spi/spi_ppc4xx.c index 6d8d4026a07a..140a18d6cf3e 100644 --- a/trunk/drivers/spi/spi_ppc4xx.c +++ b/trunk/drivers/spi/spi_ppc4xx.c @@ -578,7 +578,7 @@ static int __exit spi_ppc4xx_of_remove(struct of_device *op) return 0; } -static const struct of_device_id spi_ppc4xx_of_match[] = { +static struct of_device_id spi_ppc4xx_of_match[] = { { .compatible = "ibm,ppc4xx-spi", }, {}, }; diff --git a/trunk/drivers/spi/spi_s3c64xx.c b/trunk/drivers/spi/spi_s3c64xx.c index 97365815a729..88a456dba967 100644 --- a/trunk/drivers/spi/spi_s3c64xx.c +++ b/trunk/drivers/spi/spi_s3c64xx.c @@ -28,7 +28,7 @@ #include #include -#include +#include /* Registers and bit-fields */ @@ -137,7 +137,6 @@ /** * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. * @clk: Pointer to the spi clock. - * @src_clk: Pointer to the clock used to generate SPI signals. * @master: Pointer to the SPI Protocol master. * @workqueue: Work queue for the SPI xfer requests. * @cntrlr_info: Platform specific data for the controller this driver manages. @@ -158,11 +157,10 @@ struct s3c64xx_spi_driver_data { void __iomem *regs; struct clk *clk; - struct clk *src_clk; struct platform_device *pdev; struct spi_master *master; struct workqueue_struct *workqueue; - struct s3c64xx_spi_info *cntrlr_info; + struct s3c64xx_spi_cntrlr_info *cntrlr_info; struct spi_device *tgl_spi; struct work_struct work; struct list_head queue; @@ -182,7 +180,7 @@ static struct s3c2410_dma_client s3c64xx_spi_dma_client = { static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; unsigned long loops; u32 val; @@ -227,7 +225,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, struct spi_device *spi, struct spi_transfer *xfer, int dma_mode) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; u32 modecfg, chcfg; @@ -300,20 +298,19 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ /* Deselect the last toggled device */ cs = sdd->tgl_spi->controller_data; - cs->set_level(cs->line, - spi->mode & SPI_CS_HIGH ? 0 : 1); + cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1); } sdd->tgl_spi = NULL; } cs = spi->controller_data; - cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); + cs->set_level(spi->mode & SPI_CS_HIGH ? 1 : 0); } static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, struct spi_transfer *xfer, int dma_mode) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; unsigned long val; int ms; @@ -387,11 +384,12 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, if (sdd->tgl_spi == spi) sdd->tgl_spi = NULL; - cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); + cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1); } static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) { + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; u32 val; @@ -437,7 +435,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) /* Configure Clock */ val = readl(regs + S3C64XX_SPI_CLK_CFG); val &= ~S3C64XX_SPI_PSR_MASK; - val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1) + val |= ((clk_get_rate(sci->src_clk) / sdd->cur_speed / 2 - 1) & S3C64XX_SPI_PSR_MASK); writel(val, regs + S3C64XX_SPI_CLK_CFG); @@ -560,7 +558,7 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, static void handle_msg(struct s3c64xx_spi_driver_data *sdd, struct spi_message *msg) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; struct spi_device *spi = msg->spi; struct s3c64xx_spi_csinfo *cs = spi->controller_data; struct spi_transfer *xfer; @@ -634,8 +632,8 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd, S3C64XX_SPI_DEACT(sdd); if (status) { - dev_err(&spi->dev, "I/O Error: " - "rx-%d tx-%d res:rx-%c tx-%c len-%d\n", + dev_err(&spi->dev, "I/O Error: \ + rx-%d tx-%d res:rx-%c tx-%c len-%d\n", xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, (sdd->state & RXBUSY) ? 'f' : 'p', (sdd->state & TXBUSY) ? 'f' : 'p', @@ -788,7 +786,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs = spi->controller_data; struct s3c64xx_spi_driver_data *sdd; - struct s3c64xx_spi_info *sci; + struct s3c64xx_spi_cntrlr_info *sci; struct spi_message *msg; u32 psr, speed; unsigned long flags; @@ -833,17 +831,17 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } /* Check if we can provide the requested rate */ - speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */ + speed = clk_get_rate(sci->src_clk) / 2 / (0 + 1); /* Max possible */ if (spi->max_speed_hz > speed) spi->max_speed_hz = speed; - psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1; + psr = clk_get_rate(sci->src_clk) / 2 / spi->max_speed_hz - 1; psr &= S3C64XX_SPI_PSR_MASK; if (psr == S3C64XX_SPI_PSR_MASK) psr--; - speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); + speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1); if (spi->max_speed_hz < speed) { if (psr+1 < S3C64XX_SPI_PSR_MASK) { psr++; @@ -853,7 +851,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi) } } - speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1); + speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1); if (spi->max_speed_hz >= speed) spi->max_speed_hz = speed; else @@ -869,7 +867,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi) static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) { - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; void __iomem *regs = sdd->regs; unsigned int val; @@ -904,7 +902,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) { struct resource *mem_res, *dmatx_res, *dmarx_res; struct s3c64xx_spi_driver_data *sdd; - struct s3c64xx_spi_info *sci; + struct s3c64xx_spi_cntrlr_info *sci; struct spi_master *master; int ret; @@ -1002,15 +1000,18 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) goto err4; } - sdd->src_clk = clk_get(&pdev->dev, sci->src_clk_name); - if (IS_ERR(sdd->src_clk)) { + if (sci->src_clk_nr == S3C64XX_SPI_SRCCLK_PCLK) + sci->src_clk = sdd->clk; + else + sci->src_clk = clk_get(&pdev->dev, sci->src_clk_name); + if (IS_ERR(sci->src_clk)) { dev_err(&pdev->dev, "Unable to acquire clock '%s'\n", sci->src_clk_name); - ret = PTR_ERR(sdd->src_clk); + ret = PTR_ERR(sci->src_clk); goto err5; } - if (clk_enable(sdd->src_clk)) { + if (sci->src_clk != sdd->clk && clk_enable(sci->src_clk)) { dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", sci->src_clk_name); ret = -EBUSY; @@ -1039,10 +1040,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) goto err8; } - dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " - "with %d Slaves attached\n", + dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d \ + with %d Slaves attached\n", pdev->id, master->num_chipselect); - dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", + dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\ + \tDMA=[Rx-%d, Tx-%d]\n", mem_res->end, mem_res->start, sdd->rx_dmach, sdd->tx_dmach); @@ -1051,9 +1053,11 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) err8: destroy_workqueue(sdd->workqueue); err7: - clk_disable(sdd->src_clk); + if (sci->src_clk != sdd->clk) + clk_disable(sci->src_clk); err6: - clk_put(sdd->src_clk); + if (sci->src_clk != sdd->clk) + clk_put(sci->src_clk); err5: clk_disable(sdd->clk); err4: @@ -1074,6 +1078,7 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) { struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; struct resource *mem_res; unsigned long flags; @@ -1088,8 +1093,11 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) destroy_workqueue(sdd->workqueue); - clk_disable(sdd->src_clk); - clk_put(sdd->src_clk); + if (sci->src_clk != sdd->clk) + clk_disable(sci->src_clk); + + if (sci->src_clk != sdd->clk) + clk_put(sci->src_clk); clk_disable(sdd->clk); clk_put(sdd->clk); @@ -1097,8 +1105,7 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) iounmap((void *) sdd->regs); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem_res != NULL) - release_mem_region(mem_res->start, resource_size(mem_res)); + release_mem_region(mem_res->start, resource_size(mem_res)); platform_set_drvdata(pdev, NULL); spi_master_put(master); @@ -1111,6 +1118,8 @@ static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state) { struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_csinfo *cs; unsigned long flags; spin_lock_irqsave(&sdd->lock, flags); @@ -1121,7 +1130,9 @@ static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state) msleep(10); /* Disable the clock */ - clk_disable(sdd->src_clk); + if (sci->src_clk != sdd->clk) + clk_disable(sci->src_clk); + clk_disable(sdd->clk); sdd->cur_speed = 0; /* Output Clock is stopped */ @@ -1133,13 +1144,15 @@ static int s3c64xx_spi_resume(struct platform_device *pdev) { struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); - struct s3c64xx_spi_info *sci = sdd->cntrlr_info; + struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info; unsigned long flags; sci->cfg_gpio(pdev); /* Enable the clock */ - clk_enable(sdd->src_clk); + if (sci->src_clk != sdd->clk) + clk_enable(sci->src_clk); + clk_enable(sdd->clk); s3c64xx_spi_hwinit(sdd, pdev->id); diff --git a/trunk/drivers/spi/spi_sh_msiof.c b/trunk/drivers/spi/spi_sh_msiof.c index d93b66743ba7..30973ec16a93 100644 --- a/trunk/drivers/spi/spi_sh_msiof.c +++ b/trunk/drivers/spi/spi_sh_msiof.c @@ -20,12 +20,12 @@ #include #include #include -#include #include #include #include +#include #include struct sh_msiof_spi_priv { diff --git a/trunk/drivers/spi/spi_stmp.c b/trunk/drivers/spi/spi_stmp.c index fadff76eb7e0..2552bb364005 100644 --- a/trunk/drivers/spi/spi_stmp.c +++ b/trunk/drivers/spi/spi_stmp.c @@ -76,7 +76,7 @@ struct stmp_spi { break; \ } \ cpu_relax(); \ - } while (time_before(jiffies, end_jiffies)); \ + } while (time_before(end_jiffies, jiffies)); \ succeeded; \ }) diff --git a/trunk/drivers/spi/xilinx_spi.c b/trunk/drivers/spi/xilinx_spi.c index 1b47363cb73f..9f386379c169 100644 --- a/trunk/drivers/spi/xilinx_spi.c +++ b/trunk/drivers/spi/xilinx_spi.c @@ -93,26 +93,6 @@ struct xilinx_spi { void (*rx_fn) (struct xilinx_spi *); }; -static void xspi_write32(u32 val, void __iomem *addr) -{ - iowrite32(val, addr); -} - -static unsigned int xspi_read32(void __iomem *addr) -{ - return ioread32(addr); -} - -static void xspi_write32_be(u32 val, void __iomem *addr) -{ - iowrite32be(val, addr); -} - -static unsigned int xspi_read32_be(void __iomem *addr) -{ - return ioread32be(addr); -} - static void xspi_tx8(struct xilinx_spi *xspi) { xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET); @@ -394,11 +374,11 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->mem = *mem; xspi->irq = irq; if (pdata->little_endian) { - xspi->read_fn = xspi_read32; - xspi->write_fn = xspi_write32; + xspi->read_fn = ioread32; + xspi->write_fn = iowrite32; } else { - xspi->read_fn = xspi_read32_be; - xspi->write_fn = xspi_write32_be; + xspi->read_fn = ioread32be; + xspi->write_fn = iowrite32be; } xspi->bits_per_word = pdata->bits_per_word; if (xspi->bits_per_word == 8) { diff --git a/trunk/drivers/spi/xilinx_spi_of.c b/trunk/drivers/spi/xilinx_spi_of.c index ed34a8d419c7..71dc3adc0495 100644 --- a/trunk/drivers/spi/xilinx_spi_of.c +++ b/trunk/drivers/spi/xilinx_spi_of.c @@ -99,7 +99,7 @@ static int __exit xilinx_spi_of_remove(struct of_device *op) return xilinx_spi_remove(op); } -static const struct of_device_id xilinx_spi_of_match[] = { +static struct of_device_id xilinx_spi_of_match[] = { { .compatible = "xlnx,xps-spi-2.00.a", }, { .compatible = "xlnx,xps-spi-2.00.b", }, {} diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index bbeeb92a2131..e9f995486ec1 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -78,7 +78,7 @@ MODULE_AUTHOR("Matthew Dharm "); MODULE_DESCRIPTION("USB Mass Storage driver for Linux"); MODULE_LICENSE("GPL"); -static unsigned int delay_use = 1; +static unsigned int delay_use = 5; module_param(delay_use, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index 9ee67d6da710..e4e4d433b007 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -1931,22 +1931,22 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i * PowerMac2,2 summer 2000 iMacs * PowerMac4,1 january 2001 iMacs "flower power" */ - if (of_machine_is_compatible("PowerMac2,1") || - of_machine_is_compatible("PowerMac2,2") || - of_machine_is_compatible("PowerMac4,1")) + if (machine_is_compatible("PowerMac2,1") || + machine_is_compatible("PowerMac2,2") || + machine_is_compatible("PowerMac4,1")) default_vmode = VMODE_1024_768_75; /* iBook SE */ - if (of_machine_is_compatible("PowerBook2,2")) + if (machine_is_compatible("PowerBook2,2")) default_vmode = VMODE_800_600_60; /* PowerBook Firewire (Pismo), iBook Dual USB */ - if (of_machine_is_compatible("PowerBook3,1") || - of_machine_is_compatible("PowerBook4,1")) + if (machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook4,1")) default_vmode = VMODE_1024_768_60; /* PowerBook Titanium */ - if (of_machine_is_compatible("PowerBook3,2")) + if (machine_is_compatible("PowerBook3,2")) default_vmode = VMODE_1152_768_60; if (default_cmode > 16) diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index e45ab8db2ddc..1ddeb4c34763 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -2439,7 +2439,7 @@ static int __devinit aty_init(struct fb_info *info) * The Apple iBook1 uses non-standard memory frequencies. * We detect it and set the frequency manually. */ - if (of_machine_is_compatible("PowerBook2,1")) { + if (machine_is_compatible("PowerBook2,1")) { par->pll_limits.mclk = 70; par->pll_limits.xclk = 53; } @@ -2659,7 +2659,7 @@ static int __devinit aty_init(struct fb_info *info) FBINFO_HWACCEL_YPAN; #ifdef CONFIG_PMAC_BACKLIGHT - if (M64_HAS(G3_PB_1_1) && of_machine_is_compatible("PowerBook1,1")) { + if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { /* * these bits let the 101 powerbook * wake up from sleep -- paulus @@ -2690,9 +2690,9 @@ static int __devinit aty_init(struct fb_info *info) if (M64_HAS(G3_PB_1024x768)) /* G3 PowerBook with 1024x768 LCD */ default_vmode = VMODE_1024_768_60; - else if (of_machine_is_compatible("iMac")) + else if (machine_is_compatible("iMac")) default_vmode = VMODE_1024_768_75; - else if (of_machine_is_compatible("PowerBook2,1")) + else if (machine_is_compatible("PowerBook2,1")) /* iBook with 800x600 LCD */ default_vmode = VMODE_800_600_60; else @@ -3104,7 +3104,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, } dp = pci_device_to_OF_node(pdev); - if (node == dp->phandle) { + if (node == dp->node) { struct fb_var_screeninfo *var = &default_var; unsigned int N, P, Q, M, T, R; u32 v_total, h_total; diff --git a/trunk/drivers/video/aty/radeon_backlight.c b/trunk/drivers/video/aty/radeon_backlight.c index fa1198c4ccc5..1a056adb61c8 100644 --- a/trunk/drivers/video/aty/radeon_backlight.c +++ b/trunk/drivers/video/aty/radeon_backlight.c @@ -175,9 +175,9 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) #ifdef CONFIG_PMAC_BACKLIGHT pdata->negative = pdata->negative || - of_machine_is_compatible("PowerBook4,3") || - of_machine_is_compatible("PowerBook6,3") || - of_machine_is_compatible("PowerBook6,5"); + machine_is_compatible("PowerBook4,3") || + machine_is_compatible("PowerBook6,3") || + machine_is_compatible("PowerBook6,5"); #endif rinfo->info->bl_dev = bd; diff --git a/trunk/drivers/video/efifb.c b/trunk/drivers/video/efifb.c index d25df51bb0d2..eb12182b2059 100644 --- a/trunk/drivers/video/efifb.c +++ b/trunk/drivers/video/efifb.c @@ -161,17 +161,8 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } -static void efifb_destroy(struct fb_info *info) -{ - if (info->screen_base) - iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); - framebuffer_release(info); -} - static struct fb_ops efifb_ops = { .owner = THIS_MODULE, - .fb_destroy = efifb_destroy, .fb_setcolreg = efifb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -290,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev) info->par = NULL; info->aperture_base = efifb_fix.smem_start; - info->aperture_size = size_remap; + info->aperture_size = size_total; info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); if (!info->screen_base) { diff --git a/trunk/drivers/virtio/virtio_balloon.c b/trunk/drivers/virtio/virtio_balloon.c index 369f2eebbad1..505be88c82ae 100644 --- a/trunk/drivers/virtio/virtio_balloon.c +++ b/trunk/drivers/virtio/virtio_balloon.c @@ -28,7 +28,7 @@ struct virtio_balloon { struct virtio_device *vdev; - struct virtqueue *inflate_vq, *deflate_vq, *stats_vq; + struct virtqueue *inflate_vq, *deflate_vq; /* Where the ballooning thread waits for config to change. */ wait_queue_head_t config_change; @@ -49,10 +49,6 @@ struct virtio_balloon /* The array of pfns we tell the Host about. */ unsigned int num_pfns; u32 pfns[256]; - - /* Memory statistics */ - int need_stats_update; - struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; }; static struct virtio_device_id id_table[] = { @@ -158,72 +154,6 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) } } -static inline void update_stat(struct virtio_balloon *vb, int idx, - u16 tag, u64 val) -{ - BUG_ON(idx >= VIRTIO_BALLOON_S_NR); - vb->stats[idx].tag = tag; - vb->stats[idx].val = val; -} - -#define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) - -static void update_balloon_stats(struct virtio_balloon *vb) -{ - unsigned long events[NR_VM_EVENT_ITEMS]; - struct sysinfo i; - int idx = 0; - - all_vm_events(events); - si_meminfo(&i); - - update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, - pages_to_bytes(events[PSWPIN])); - update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_OUT, - pages_to_bytes(events[PSWPOUT])); - update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]); - update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]); - update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE, - pages_to_bytes(i.freeram)); - update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMTOT, - pages_to_bytes(i.totalram)); -} - -/* - * While most virtqueues communicate guest-initiated requests to the hypervisor, - * the stats queue operates in reverse. The driver initializes the virtqueue - * with a single buffer. From that point forward, all conversations consist of - * a hypervisor request (a call to this function) which directs us to refill - * the virtqueue with a fresh stats buffer. Since stats collection can sleep, - * we notify our kthread which does the actual work via stats_handle_request(). - */ -static void stats_request(struct virtqueue *vq) -{ - struct virtio_balloon *vb; - unsigned int len; - - vb = vq->vq_ops->get_buf(vq, &len); - if (!vb) - return; - vb->need_stats_update = 1; - wake_up(&vb->config_change); -} - -static void stats_handle_request(struct virtio_balloon *vb) -{ - struct virtqueue *vq; - struct scatterlist sg; - - vb->need_stats_update = 0; - update_balloon_stats(vb); - - vq = vb->stats_vq; - sg_init_one(&sg, vb->stats, sizeof(vb->stats)); - if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) - BUG(); - vq->vq_ops->kick(vq); -} - static void virtballoon_changed(struct virtio_device *vdev) { struct virtio_balloon *vb = vdev->priv; @@ -260,11 +190,8 @@ static int balloon(void *_vballoon) try_to_freeze(); wait_event_interruptible(vb->config_change, (diff = towards_target(vb)) != 0 - || vb->need_stats_update || kthread_should_stop() || freezing(current)); - if (vb->need_stats_update) - stats_handle_request(vb); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) @@ -277,10 +204,10 @@ static int balloon(void *_vballoon) static int virtballoon_probe(struct virtio_device *vdev) { struct virtio_balloon *vb; - struct virtqueue *vqs[3]; - vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request }; - const char *names[] = { "inflate", "deflate", "stats" }; - int err, nvqs; + struct virtqueue *vqs[2]; + vq_callback_t *callbacks[] = { balloon_ack, balloon_ack }; + const char *names[] = { "inflate", "deflate" }; + int err; vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); if (!vb) { @@ -292,31 +219,14 @@ static int virtballoon_probe(struct virtio_device *vdev) vb->num_pages = 0; init_waitqueue_head(&vb->config_change); vb->vdev = vdev; - vb->need_stats_update = 0; - /* We expect two virtqueues: inflate and deflate, - * and optionally stat. */ - nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; - err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names); + /* We expect two virtqueues. */ + err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); if (err) goto out_free_vb; vb->inflate_vq = vqs[0]; vb->deflate_vq = vqs[1]; - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { - struct scatterlist sg; - vb->stats_vq = vqs[2]; - - /* - * Prime this virtqueue with one buffer so the hypervisor can - * use it to signal us later. - */ - sg_init_one(&sg, vb->stats, sizeof vb->stats); - if (vb->stats_vq->vq_ops->add_buf(vb->stats_vq, - &sg, 1, 0, vb) < 0) - BUG(); - vb->stats_vq->vq_ops->kick(vb->stats_vq); - } vb->thread = kthread_run(balloon, vb, "vballoon"); if (IS_ERR(vb->thread)) { @@ -354,10 +264,7 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev) kfree(vb); } -static unsigned int features[] = { - VIRTIO_BALLOON_F_MUST_TELL_HOST, - VIRTIO_BALLOON_F_STATS_VQ, -}; +static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST }; static struct virtio_driver virtio_balloon_driver = { .feature_table = features, diff --git a/trunk/drivers/virtio/virtio_pci.c b/trunk/drivers/virtio/virtio_pci.c index 1d5191fab62e..28d9cf7cf72f 100644 --- a/trunk/drivers/virtio/virtio_pci.c +++ b/trunk/drivers/virtio/virtio_pci.c @@ -702,7 +702,7 @@ static struct pci_driver virtio_pci_driver = { .name = "virtio-pci", .id_table = virtio_pci_id_table, .probe = virtio_pci_probe, - .remove = __devexit_p(virtio_pci_remove), + .remove = virtio_pci_remove, #ifdef CONFIG_PM .suspend = virtio_pci_suspend, .resume = virtio_pci_resume, diff --git a/trunk/drivers/virtio/virtio_ring.c b/trunk/drivers/virtio/virtio_ring.c index 0db906b3c95d..fbd2ecde93e4 100644 --- a/trunk/drivers/virtio/virtio_ring.c +++ b/trunk/drivers/virtio/virtio_ring.c @@ -21,24 +21,6 @@ #include #include -/* virtio guest is communicating with a virtual "device" that actually runs on - * a host processor. Memory barriers are used to control SMP effects. */ -#ifdef CONFIG_SMP -/* Where possible, use SMP barriers which are more lightweight than mandatory - * barriers, because mandatory barriers control MMIO effects on accesses - * through relaxed memory I/O windows (which virtio does not use). */ -#define virtio_mb() smp_mb() -#define virtio_rmb() smp_rmb() -#define virtio_wmb() smp_wmb() -#else -/* We must force memory ordering even if guest is UP since host could be - * running on another CPU, but SMP barriers are defined to barrier() in that - * configuration. So fall back to mandatory barriers instead. */ -#define virtio_mb() mb() -#define virtio_rmb() rmb() -#define virtio_wmb() wmb() -#endif - #ifdef DEBUG /* For development, we want to crash whenever the ring is screwed. */ #define BAD_RING(_vq, fmt, args...) \ @@ -54,9 +36,10 @@ panic("%s:in_use = %i\n", \ (_vq)->vq.name, (_vq)->in_use); \ (_vq)->in_use = __LINE__; \ + mb(); \ } while (0) #define END_USE(_vq) \ - do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; } while(0) + do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; mb(); } while(0) #else #define BAD_RING(_vq, fmt, args...) \ do { \ @@ -238,13 +221,13 @@ static void vring_kick(struct virtqueue *_vq) START_USE(vq); /* Descriptors and available array need to be set before we expose the * new available array entries. */ - virtio_wmb(); + wmb(); vq->vring.avail->idx += vq->num_added; vq->num_added = 0; /* Need to update avail index before checking if we should notify */ - virtio_mb(); + mb(); if (!(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY)) /* Prod other side to tell it about changes. */ @@ -303,7 +286,7 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len) } /* Only get used array entries after they have been exposed by host. */ - virtio_rmb(); + rmb(); i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id; *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len; @@ -341,7 +324,7 @@ static bool vring_enable_cb(struct virtqueue *_vq) /* We optimistically turn back on interrupts, then check if there was * more to do. */ vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - virtio_mb(); + mb(); if (unlikely(more_used(vq))) { END_USE(vq); return false; @@ -351,30 +334,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) return true; } -static void *vring_detach_unused_buf(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - unsigned int i; - void *buf; - - START_USE(vq); - - for (i = 0; i < vq->vring.num; i++) { - if (!vq->data[i]) - continue; - /* detach_buf clears data, so grab it now. */ - buf = vq->data[i]; - detach_buf(vq, i); - END_USE(vq); - return buf; - } - /* That should have freed everything. */ - BUG_ON(vq->num_free != vq->vring.num); - - END_USE(vq); - return NULL; -} - irqreturn_t vring_interrupt(int irq, void *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); @@ -401,7 +360,6 @@ static struct virtqueue_ops vring_vq_ops = { .kick = vring_kick, .disable_cb = vring_disable_cb, .enable_cb = vring_enable_cb, - .detach_unused_buf = vring_detach_unused_buf, }; struct virtqueue *vring_new_virtqueue(unsigned int num, @@ -448,11 +406,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, /* Put everything in free lists. */ vq->num_free = num; vq->free_head = 0; - for (i = 0; i < num-1; i++) { + for (i = 0; i < num-1; i++) vq->vring.desc[i].next = i+1; - vq->data[i] = NULL; - } - vq->data[i] = NULL; return &vq->vq; } diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index cce6bbdbdbb1..e95c692ef0e4 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -637,6 +637,7 @@ int setup_arg_pages(struct linux_binprm *bprm, * will align it up. */ rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK; + rlim_stack = min(rlim_stack, stack_size); #ifdef CONFIG_STACK_GROWSUP if (stack_size + stack_expand > rlim_stack) stack_base = vma->vm_start + rlim_stack; diff --git a/trunk/fs/proc/proc_devtree.c b/trunk/fs/proc/proc_devtree.c index f8650dce74fb..123257bb356b 100644 --- a/trunk/fs/proc/proc_devtree.c +++ b/trunk/fs/proc/proc_devtree.c @@ -10,19 +10,16 @@ #include #include #include -#include -#include #include #include #include "internal.h" +#ifndef HAVE_ARCH_DEVTREE_FIXUPS static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de) { -#ifdef HAVE_ARCH_DEVTREE_FIXUPS - np->pde = de; -#endif } +#endif static struct proc_dir_entry *proc_device_tree; diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 1896e868854f..5c8018977efa 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -461,7 +461,8 @@ struct request_queue #define QUEUE_FLAG_NONROT 14 /* non-rotational device (SSD) */ #define QUEUE_FLAG_VIRT QUEUE_FLAG_NONROT /* paravirt device */ #define QUEUE_FLAG_IO_STAT 15 /* do IO stats */ -#define QUEUE_FLAG_DISCARD 16 /* supports DISCARD */ +#define QUEUE_FLAG_CQ 16 /* hardware does queuing */ +#define QUEUE_FLAG_DISCARD 17 /* supports DISCARD */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_CLUSTER) | \ @@ -585,6 +586,7 @@ enum { #define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) +#define blk_queue_queuing(q) test_bit(QUEUE_FLAG_CQ, &(q)->queue_flags) #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags) #define blk_queue_nonrot(q) test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags) diff --git a/trunk/include/linux/hid.h b/trunk/include/linux/hid.h index b1344ec4b7fc..87093652dda8 100644 --- a/trunk/include/linux/hid.h +++ b/trunk/include/linux/hid.h @@ -501,7 +501,7 @@ struct hid_device { /* device report descriptor */ void (*hiddev_report_event) (struct hid_device *, struct hid_report *); /* handler for raw output data, used by hidraw */ - int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char); + int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t); /* debugging support via debugfs */ unsigned short debug; @@ -663,7 +663,7 @@ struct hid_ll_driver { /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ /* We ignore a few input applications that are not widely used */ -#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || ((a >= 0x000d0002) && (a <= 0x000d0006))) +#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002)) /* HID core API */ @@ -690,7 +690,6 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); -struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index f44ee9114401..663208afb64c 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -598,48 +598,6 @@ struct input_absinfo { #define KEY_CAMERA_FOCUS 0x210 -#define BTN_TRIGGER_HAPPY 0x2c0 -#define BTN_TRIGGER_HAPPY1 0x2c0 -#define BTN_TRIGGER_HAPPY2 0x2c1 -#define BTN_TRIGGER_HAPPY3 0x2c2 -#define BTN_TRIGGER_HAPPY4 0x2c3 -#define BTN_TRIGGER_HAPPY5 0x2c4 -#define BTN_TRIGGER_HAPPY6 0x2c5 -#define BTN_TRIGGER_HAPPY7 0x2c6 -#define BTN_TRIGGER_HAPPY8 0x2c7 -#define BTN_TRIGGER_HAPPY9 0x2c8 -#define BTN_TRIGGER_HAPPY10 0x2c9 -#define BTN_TRIGGER_HAPPY11 0x2ca -#define BTN_TRIGGER_HAPPY12 0x2cb -#define BTN_TRIGGER_HAPPY13 0x2cc -#define BTN_TRIGGER_HAPPY14 0x2cd -#define BTN_TRIGGER_HAPPY15 0x2ce -#define BTN_TRIGGER_HAPPY16 0x2cf -#define BTN_TRIGGER_HAPPY17 0x2d0 -#define BTN_TRIGGER_HAPPY18 0x2d1 -#define BTN_TRIGGER_HAPPY19 0x2d2 -#define BTN_TRIGGER_HAPPY20 0x2d3 -#define BTN_TRIGGER_HAPPY21 0x2d4 -#define BTN_TRIGGER_HAPPY22 0x2d5 -#define BTN_TRIGGER_HAPPY23 0x2d6 -#define BTN_TRIGGER_HAPPY24 0x2d7 -#define BTN_TRIGGER_HAPPY25 0x2d8 -#define BTN_TRIGGER_HAPPY26 0x2d9 -#define BTN_TRIGGER_HAPPY27 0x2da -#define BTN_TRIGGER_HAPPY28 0x2db -#define BTN_TRIGGER_HAPPY29 0x2dc -#define BTN_TRIGGER_HAPPY30 0x2dd -#define BTN_TRIGGER_HAPPY31 0x2de -#define BTN_TRIGGER_HAPPY32 0x2df -#define BTN_TRIGGER_HAPPY33 0x2e0 -#define BTN_TRIGGER_HAPPY34 0x2e1 -#define BTN_TRIGGER_HAPPY35 0x2e2 -#define BTN_TRIGGER_HAPPY36 0x2e3 -#define BTN_TRIGGER_HAPPY37 0x2e4 -#define BTN_TRIGGER_HAPPY38 0x2e5 -#define BTN_TRIGGER_HAPPY39 0x2e6 -#define BTN_TRIGGER_HAPPY40 0x2e7 - /* We avoid low common keys in module aliases so they don't get huge. */ #define KEY_MIN_INTERESTING KEY_MUTE #define KEY_MAX 0x2ff diff --git a/trunk/include/linux/of.h b/trunk/include/linux/of.h index f6d9cbc39c9c..e7facd8fbce8 100644 --- a/trunk/include/linux/of.h +++ b/trunk/include/linux/of.h @@ -19,11 +19,6 @@ #include #include #include -#include - -#include - -#ifdef CONFIG_OF typedef u32 phandle; typedef u32 ihandle; @@ -44,7 +39,10 @@ struct of_irq_controller; struct device_node { const char *name; const char *type; - phandle phandle; + phandle node; +#if !defined(CONFIG_SPARC) + phandle linux_phandle; +#endif char *full_name; struct property *properties; @@ -65,11 +63,6 @@ struct device_node { #endif }; -/* Pointer for first entry in chain of all nodes. */ -extern struct device_node *allnodes; -extern struct device_node *of_chosen; -extern rwlock_t devtree_lock; - static inline int of_node_check_flag(struct device_node *n, unsigned long flag) { return test_bit(flag, &n->_flags); @@ -80,6 +73,12 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag) set_bit(flag, &n->_flags); } +static inline void +set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->pde = de; +} + extern struct device_node *of_find_all_nodes(struct device_node *prev); #if defined(CONFIG_SPARC) @@ -102,35 +101,25 @@ extern void of_node_put(struct device_node *node); */ /* Helper to read a big number; size is in cells (not bytes) */ -static inline u64 of_read_number(const __be32 *cell, int size) +static inline u64 of_read_number(const u32 *cell, int size) { u64 r = 0; while (size--) - r = (r << 32) | be32_to_cpu(*(cell++)); + r = (r << 32) | *(cell++); return r; } /* Like of_read_number, but we want an unsigned long result */ -static inline unsigned long of_read_ulong(const __be32 *cell, int size) +#ifdef CONFIG_PPC32 +static inline unsigned long of_read_ulong(const u32 *cell, int size) { - /* toss away upper bits if unsigned long is smaller than u64 */ - return of_read_number(cell, size); + return cell[size-1]; } - -#include - -/* Default #address and #size cells. Allow arch asm/prom.h to override */ -#if !defined(OF_ROOT_NODE_ADDR_CELLS_DEFAULT) -#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1 -#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 +#else +#define of_read_ulong(cell, size) of_read_number(cell, size) #endif -/* Default string compare functions, Allow arch asm/prom.h to override */ -#if !defined(of_compat_cmp) -#define of_compat_cmp(s1, s2, l) strncasecmp((s1), (s2), (l)) -#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) -#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) -#endif +#include /* flag descriptions */ #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ @@ -198,19 +187,4 @@ extern int of_parse_phandles_with_args(struct device_node *np, const char *list_name, const char *cells_name, int index, struct device_node **out_node, const void **out_args); -extern int of_machine_is_compatible(const char *compat); - -extern int prom_add_property(struct device_node* np, struct property* prop); -extern int prom_remove_property(struct device_node *np, struct property *prop); -extern int prom_update_property(struct device_node *np, - struct property *newprop, - struct property *oldprop); - -#if defined(CONFIG_OF_DYNAMIC) -/* For updating the device tree at runtime */ -extern void of_attach_node(struct device_node *); -extern void of_detach_node(struct device_node *); -#endif - -#endif /* CONFIG_OF */ #endif /* _LINUX_OF_H */ diff --git a/trunk/include/linux/of_fdt.h b/trunk/include/linux/of_fdt.h index a1ca92ccb0ff..41d432b13553 100644 --- a/trunk/include/linux/of_fdt.h +++ b/trunk/include/linux/of_fdt.h @@ -42,62 +42,45 @@ * ends when size is 0 */ struct boot_param_header { - __be32 magic; /* magic word OF_DT_HEADER */ - __be32 totalsize; /* total size of DT block */ - __be32 off_dt_struct; /* offset to structure */ - __be32 off_dt_strings; /* offset to strings */ - __be32 off_mem_rsvmap; /* offset to memory reserve map */ - __be32 version; /* format version */ - __be32 last_comp_version; /* last compatible version */ + u32 magic; /* magic word OF_DT_HEADER */ + u32 totalsize; /* total size of DT block */ + u32 off_dt_struct; /* offset to structure */ + u32 off_dt_strings; /* offset to strings */ + u32 off_mem_rsvmap; /* offset to memory reserve map */ + u32 version; /* format version */ + u32 last_comp_version; /* last compatible version */ /* version 2 fields below */ - __be32 boot_cpuid_phys; /* Physical CPU id we're booting on */ + u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ /* version 3 fields below */ - __be32 dt_strings_size; /* size of the DT strings block */ + u32 dt_strings_size; /* size of the DT strings block */ /* version 17 fields below */ - __be32 dt_struct_size; /* size of the DT structure block */ + u32 dt_struct_size; /* size of the DT structure block */ }; -/* TBD: Temporary export of fdt globals - remove when code fully merged */ -extern int __initdata dt_root_addr_cells; -extern int __initdata dt_root_size_cells; -extern struct boot_param_header *initial_boot_params; - /* For scanning the flat device-tree at boot time */ -extern char *find_flat_dt_string(u32 offset); -extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, - int depth, void *data), - void *data); -extern void *of_get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size); -extern int of_flat_dt_is_compatible(unsigned long node, const char *name); -extern unsigned long of_get_flat_dt_root(void); -extern void early_init_dt_scan_chosen_arch(unsigned long node); -extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, - int depth, void *data); -extern void early_init_dt_check_for_initrd(unsigned long node); -extern int early_init_dt_scan_memory(unsigned long node, const char *uname, - int depth, void *data); -extern void early_init_dt_add_memory_arch(u64 base, u64 size); -extern u64 early_init_dt_alloc_memory_arch(u64 size, u64 align); -extern u64 dt_mem_next_cell(int s, __be32 **cellp); - -/* - * If BLK_DEV_INITRD, the fdt early init code will call this function, - * to be provided by the arch code. start and end are specified as - * physical addresses. - */ -#ifdef CONFIG_BLK_DEV_INITRD -extern void early_init_dt_setup_initrd_arch(unsigned long start, - unsigned long end); -#endif - -/* Early flat tree scan hooks */ -extern int early_init_dt_scan_root(unsigned long node, const char *uname, - int depth, void *data); +extern int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +extern void __init *of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); +extern int __init of_flat_dt_is_compatible(unsigned long node, + const char *name); +extern unsigned long __init of_get_flat_dt_root(void); /* Other Prototypes */ +extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); +extern int machine_is_compatible(const char *compat); +extern void print_properties(struct device_node *node); +extern int prom_n_intr_cells(struct device_node* np); +extern void prom_get_irq_senses(unsigned char *senses, int off, int max); +extern int prom_add_property(struct device_node* np, struct property* prop); +extern int prom_remove_property(struct device_node *np, struct property *prop); +extern int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop); #endif /* __ASSEMBLY__ */ #endif /* _LINUX_OF_FDT_H */ diff --git a/trunk/include/linux/spi/dw_spi.h b/trunk/include/linux/spi/dw_spi.h index cc813f95a2f2..51b3e771a9a3 100644 --- a/trunk/include/linux/spi/dw_spi.h +++ b/trunk/include/linux/spi/dw_spi.h @@ -90,7 +90,6 @@ struct dw_spi { unsigned long paddr; u32 iolen; int irq; - u32 fifo_len; /* depth of the FIFO buffer */ u32 max_freq; /* max bus freq supported */ u16 bus_num; @@ -172,10 +171,6 @@ static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) { if (cs > dws->num_cs) return; - - if (dws->cs_control) - dws->cs_control(1); - dw_writel(dws, ser, 1 << cs); } diff --git a/trunk/include/linux/virtio.h b/trunk/include/linux/virtio.h index f508c651e53d..057a2e010758 100644 --- a/trunk/include/linux/virtio.h +++ b/trunk/include/linux/virtio.h @@ -51,9 +51,6 @@ struct virtqueue { * This re-enables callbacks; it returns "false" if there are pending * buffers in the queue, to detect a possible race between the driver * checking for more work, and enabling callbacks. - * @detach_unused_buf: detach first unused buffer - * vq: the struct virtqueue we're talking about. - * Returns NULL or the "data" token handed to add_buf * * Locking rules are straightforward: the driver is responsible for * locking. No two operations may be invoked simultaneously, with the exception @@ -74,7 +71,6 @@ struct virtqueue_ops { void (*disable_cb)(struct virtqueue *vq); bool (*enable_cb)(struct virtqueue *vq); - void *(*detach_unused_buf)(struct virtqueue *vq); }; /** diff --git a/trunk/include/linux/virtio_balloon.h b/trunk/include/linux/virtio_balloon.h index a50ecd1b81a2..1418f048cb34 100644 --- a/trunk/include/linux/virtio_balloon.h +++ b/trunk/include/linux/virtio_balloon.h @@ -7,7 +7,6 @@ /* The feature bitmap for virtio balloon */ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ -#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */ /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 @@ -19,18 +18,4 @@ struct virtio_balloon_config /* Number of pages we've actually got in balloon. */ __le32 actual; }; - -#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ -#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */ -#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */ -#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ -#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ -#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ -#define VIRTIO_BALLOON_S_NR 6 - -struct virtio_balloon_stat { - u16 tag; - u64 val; -} __attribute__((packed)); - #endif /* _LINUX_VIRTIO_BALLOON_H */ diff --git a/trunk/include/linux/virtio_blk.h b/trunk/include/linux/virtio_blk.h index e52029e98919..fd294c56d571 100644 --- a/trunk/include/linux/virtio_blk.h +++ b/trunk/include/linux/virtio_blk.h @@ -15,7 +15,6 @@ #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ #define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ #define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */ -#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ struct virtio_blk_config { /* The capacity (in 512-byte sectors). */ @@ -30,20 +29,8 @@ struct virtio_blk_config { __u8 heads; __u8 sectors; } geometry; - /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ __u32 blk_size; - - /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ - /* exponent for physical block per logical block. */ - __u8 physical_block_exp; - /* alignment offset in logical blocks. */ - __u8 alignment_offset; - /* minimum I/O size without performance penalty in logical blocks. */ - __u16 min_io_size; - /* optimal sustained I/O size in logical blocks. */ - __u32 opt_io_size; - } __attribute__((packed)); /* diff --git a/trunk/include/linux/virtio_console.h b/trunk/include/linux/virtio_console.h index ae4f039515b4..fe885174cc1f 100644 --- a/trunk/include/linux/virtio_console.h +++ b/trunk/include/linux/virtio_console.h @@ -3,45 +3,19 @@ #include #include #include -/* - * This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so - * anyone can use the definitions to implement compatible drivers/servers. - * - * Copyright (C) Red Hat, Inc., 2009, 2010 - */ +/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so + * anyone can use the definitions to implement compatible drivers/servers. */ /* Feature bits */ #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ -#define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ struct virtio_console_config { /* colums of the screens */ __u16 cols; /* rows of the screens */ __u16 rows; - /* max. number of ports this device can hold */ - __u32 max_nr_ports; - /* number of ports added so far */ - __u32 nr_ports; } __attribute__((packed)); -/* - * A message that's passed between the Host and the Guest for a - * particular port. - */ -struct virtio_console_control { - __u32 id; /* Port number */ - __u16 event; /* The kind of control event (see below) */ - __u16 value; /* Extra information for the key */ -}; - -/* Some events for control messages */ -#define VIRTIO_CONSOLE_PORT_READY 0 -#define VIRTIO_CONSOLE_CONSOLE_PORT 1 -#define VIRTIO_CONSOLE_RESIZE 2 -#define VIRTIO_CONSOLE_PORT_OPEN 3 -#define VIRTIO_CONSOLE_PORT_NAME 4 -#define VIRTIO_CONSOLE_PORT_REMOVE 5 #ifdef __KERNEL__ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index 18bde979f346..26a6b73a6b85 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -222,7 +222,6 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) if (which > PRIO_USER || which < PRIO_PROCESS) return -EINVAL; - rcu_read_lock(); read_lock(&tasklist_lock); switch (which) { case PRIO_PROCESS: @@ -268,7 +267,6 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) } out_unlock: read_unlock(&tasklist_lock); - rcu_read_unlock(); return retval; } diff --git a/trunk/lib/idr.c b/trunk/lib/idr.c index 0dc782216d4b..1cac726c44bc 100644 --- a/trunk/lib/idr.c +++ b/trunk/lib/idr.c @@ -156,12 +156,10 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; /* if already at the top layer, we need to grow */ - if (id >= 1 << (idp->layers * IDR_BITS)) { + if (!(p = pa[l])) { *starting_id = id; return IDR_NEED_TO_GROW; } - p = pa[l]; - BUG_ON(!p); /* If we need to go up one layer, continue the * loop; otherwise, restart from the top. diff --git a/trunk/mm/oom_kill.c b/trunk/mm/oom_kill.c index 237050478f28..f52481b1c1e5 100644 --- a/trunk/mm/oom_kill.c +++ b/trunk/mm/oom_kill.c @@ -459,8 +459,6 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, list_for_each_entry(c, &p->children, sibling) { if (c->mm == p->mm) continue; - if (mem && !task_in_mem_cgroup(c, mem)) - continue; if (!oom_kill_task(c)) return 0; } diff --git a/trunk/net/bluetooth/hidp/core.c b/trunk/net/bluetooth/hidp/core.c index 280529ad9274..fc6ec1e72652 100644 --- a/trunk/net/bluetooth/hidp/core.c +++ b/trunk/net/bluetooth/hidp/core.c @@ -313,21 +313,10 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep return hidp_queue_report(session, buf, rsize); } -static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, - unsigned char report_type) +static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count) { - switch (report_type) { - case HID_FEATURE_REPORT: - report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE; - break; - case HID_OUTPUT_REPORT: - report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; - break; - default: - return -EINVAL; - } - - if (hidp_send_ctrl_message(hid->driver_data, report_type, + if (hidp_send_ctrl_message(hid->driver_data, + HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE, data, count)) return -ENOMEM; return count; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index ec874218b206..be9924f60ec3 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2761,7 +2761,7 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, switch (ret) { case GRO_NORMAL: case GRO_HELD: - skb->protocol = eth_type_trans(skb, skb->dev); + skb->protocol = eth_type_trans(skb, napi->dev); if (ret == GRO_HELD) skb_gro_pull(skb, -ETH_HLEN); diff --git a/trunk/scripts/.gitignore b/trunk/scripts/.gitignore index c5d5db54c009..52cab46ae35a 100644 --- a/trunk/scripts/.gitignore +++ b/trunk/scripts/.gitignore @@ -6,4 +6,5 @@ kallsyms pnmtologo bin2c unifdef +binoffset ihex2fw diff --git a/trunk/scripts/binoffset.c b/trunk/scripts/binoffset.c new file mode 100644 index 000000000000..1a2e39b8e3e5 --- /dev/null +++ b/trunk/scripts/binoffset.c @@ -0,0 +1,163 @@ +/*************************************************************************** + * binoffset.c + * (C) 2002 Randy Dunlap + +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +# binoffset.c: +# - searches a (binary) file for a specified (binary) pattern +# - returns the offset of the located pattern or ~0 if not found +# - exits with exit status 0 normally or non-0 if pattern is not found +# or any other error occurs. + +****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "0.1" +#define BUF_SIZE (16 * 1024) +#define PAT_SIZE 100 + +char *progname; +char *inputname; +int inputfd; +unsigned int bix; /* buf index */ +unsigned char patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */ +int pat_len; /* actual number of pattern bytes */ +unsigned char *madr; /* mmap address */ +size_t filesize; +int num_matches = 0; +off_t firstloc = 0; + +void usage (void) +{ + fprintf (stderr, "%s ver. %s\n", progname, VERSION); + fprintf (stderr, "usage: %s filename pattern_bytes\n", + progname); + fprintf (stderr, " [prints location of pattern_bytes in file]\n"); + exit (1); +} + +void get_pattern (int pat_count, char *pats []) +{ + int ix, err, tmp; + +#ifdef DEBUG + fprintf (stderr,"get_pattern: count = %d\n", pat_count); + for (ix = 0; ix < pat_count; ix++) + fprintf (stderr, " pat # %d: [%s]\n", ix, pats[ix]); +#endif + + for (ix = 0; ix < pat_count; ix++) { + tmp = 0; + err = sscanf (pats[ix], "%5i", &tmp); + if (err != 1 || tmp > 0xff) { + fprintf (stderr, "pattern or value error in pattern # %d [%s]\n", + ix, pats[ix]); + usage (); + } + patterns [ix] = tmp; + } + pat_len = pat_count; +} + +void search_pattern (void) +{ + for (bix = 0; bix < filesize; bix++) { + if (madr[bix] == patterns[0]) { + if (memcmp (&madr[bix], patterns, pat_len) == 0) { + if (num_matches == 0) + firstloc = bix; + num_matches++; + } + } + } +} + +#ifdef NOTDEF +size_t get_filesize (int fd) +{ + off_t end_off = lseek (fd, 0, SEEK_END); + lseek (fd, 0, SEEK_SET); + return (size_t) end_off; +} +#endif + +size_t get_filesize (int fd) +{ + int err; + struct stat stat; + + err = fstat (fd, &stat); + fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size); + if (err < 0) + return err; + return (size_t) stat.st_size; +} + +int main (int argc, char *argv []) +{ + progname = argv[0]; + + if (argc < 3) + usage (); + + get_pattern (argc - 2, argv + 2); + + inputname = argv[1]; + + inputfd = open (inputname, O_RDONLY); + if (inputfd == -1) { + fprintf (stderr, "%s: cannot open '%s'\n", + progname, inputname); + exit (3); + } + + filesize = get_filesize (inputfd); + + madr = mmap (0, filesize, PROT_READ, MAP_PRIVATE, inputfd, 0); + if (madr == MAP_FAILED) { + fprintf (stderr, "mmap error = %d\n", errno); + close (inputfd); + exit (4); + } + + search_pattern (); + + if (munmap (madr, filesize)) + fprintf (stderr, "munmap error = %d\n", errno); + + if (close (inputfd)) + fprintf (stderr, "%s: error %d closing '%s'\n", + progname, errno, inputname); + + fprintf (stderr, "number of pattern matches = %d\n", num_matches); + if (num_matches == 0) + firstloc = ~0; + printf ("%ld\n", firstloc); + fprintf (stderr, "%ld\n", firstloc); + + exit (num_matches ? 0 : 2); +} + +/* end binoffset.c */ diff --git a/trunk/scripts/extract-ikconfig b/trunk/scripts/extract-ikconfig index 37f30d36c944..de233ff43c1c 100755 --- a/trunk/scripts/extract-ikconfig +++ b/trunk/scripts/extract-ikconfig @@ -1,53 +1,92 @@ #!/bin/sh -# ---------------------------------------------------------------------- -# extract-ikconfig - Extract the .config file from a kernel image -# -# This will only work when the kernel was compiled with CONFIG_IKCONFIG. -# -# The obscure use of the "tr" filter is to work around older versions of -# "grep" that report the byte offset of the line instead of the pattern. -# -# (c) 2009, Dick Streefland -# Licensed under the terms of the GNU General Public License. -# ---------------------------------------------------------------------- - -gz1='\037\213\010' -gz2='01' -cf1='IKCFG_ST\037\213\010' -cf2='0123456789' - -dump_config() +# extracts .config info from a [b]zImage file +# uses: binoffset (new), dd, zcat, strings, grep +# $arg1 is [b]zImage filename + +binoffset="./scripts/binoffset" +test -e $binoffset || cc -o $binoffset ./scripts/binoffset.c || exit 1 + +IKCFG_ST="0x49 0x4b 0x43 0x46 0x47 0x5f 0x53 0x54" +IKCFG_ED="0x49 0x4b 0x43 0x46 0x47 0x5f 0x45 0x44" +dump_config() { + file="$1" + + start=`$binoffset $file $IKCFG_ST 2>/dev/null` + [ "$?" != "0" ] && start="-1" + if [ "$start" -eq "-1" ]; then + return + fi + end=`$binoffset $file $IKCFG_ED 2>/dev/null` + [ "$?" != "0" ] && end="-1" + if [ "$end" -eq "-1" ]; then + return + fi + + start=`expr $start + 8` + size=`expr $end - $start` + + dd if="$file" ibs=1 skip="$start" count="$size" 2>/dev/null | zcat + + clean_up + exit 0 +} + + +usage() +{ + echo " usage: extract-ikconfig [b]zImage_filename" +} + +clean_up() { - if pos=`tr "$cf1\n$cf2" "\n$cf2=" < "$1" | grep -abo "^$cf2"` - then - pos=${pos%%:*} - tail -c+$(($pos+8)) "$1" | zcat -q - exit 0 + if [ "$TMPFILE" != "" ]; then + rm -f $TMPFILE fi } -# Check invocation: -me=${0##*/} -img=$1 -if [ $# -ne 1 -o ! -s "$img" ] +if [ $# -lt 1 ] then - echo "Usage: $me " >&2 - exit 2 + usage + exit 1 fi -# Initial attempt for uncompressed images or objects: -dump_config "$img" - -# That didn't work, so decompress and try again: -tmp=/tmp/ikconfig$$ -trap "rm -f $tmp" 0 -for pos in `tr "$gz1\n$gz2" "\n$gz2=" < "$img" | grep -abo "^$gz2"` -do - pos=${pos%%:*} - tail -c+$pos "$img" | zcat 2> /dev/null > $tmp - dump_config $tmp -done - -# Bail out: -echo "$me: Cannot find kernel config." >&2 +TMPFILE=`mktemp -t ikconfig-XXXXXX` || exit 1 +image="$1" + +# vmlinux: Attempt to dump the configuration from the file directly +dump_config "$image" + +GZHDR1="0x1f 0x8b 0x08 0x00" +GZHDR2="0x1f 0x8b 0x08 0x08" + +ELFHDR="0x7f 0x45 0x4c 0x46" + +# vmlinux.gz: Check for a compressed images +off=`$binoffset "$image" $GZHDR1 2>/dev/null` +[ "$?" != "0" ] && off="-1" +if [ "$off" -eq "-1" ]; then + off=`$binoffset "$image" $GZHDR2 2>/dev/null` + [ "$?" != "0" ] && off="-1" +fi +if [ "$off" -eq "0" ]; then + zcat <"$image" >"$TMPFILE" + dump_config "$TMPFILE" +elif [ "$off" -ne "-1" ]; then + (dd ibs="$off" skip=1 count=0 && dd bs=512k) <"$image" 2>/dev/null | \ + zcat >"$TMPFILE" + dump_config "$TMPFILE" + +# check if this is simply an ELF file +else + off=`$binoffset "$image" $ELFHDR 2>/dev/null` + [ "$?" != "0" ] && off="-1" + if [ "$off" -eq "0" ]; then + dump_config "$image" + fi +fi + +echo "ERROR: Unable to extract kernel configuration information." +echo " This kernel image may not have the config info." + +clean_up exit 1 diff --git a/trunk/scripts/kconfig/Makefile b/trunk/scripts/kconfig/Makefile index 186c46604d06..999e8a7d5bf7 100644 --- a/trunk/scripts/kconfig/Makefile +++ b/trunk/scripts/kconfig/Makefile @@ -30,17 +30,8 @@ silentoldconfig: $(obj)/conf $(Q)mkdir -p include/generated $< -s $(Kconfig) -# if no path is given, then use src directory to find file -ifdef LSMOD -LSMOD_F := $(LSMOD) -ifeq ($(findstring /,$(LSMOD)),) - LSMOD_F := $(objtree)/$(LSMOD) -endif -endif - localmodconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config + $(Q)perl $< $(srctree) $(Kconfig) > .tmp.config $(Q)if [ -f .config ]; then \ cmp -s .tmp.config .config || \ (mv -f .config .config.old.1; \ @@ -54,8 +45,7 @@ localmodconfig: $(obj)/streamline_config.pl $(obj)/conf $(Q)rm -f .tmp.config localyesconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config + $(Q)perl $< $(srctree) $(Kconfig) > .tmp.config $(Q)sed -i s/=m/=y/ .tmp.config $(Q)if [ -f .config ]; then \ cmp -s .tmp.config .config || \ diff --git a/trunk/scripts/kconfig/streamline_config.pl b/trunk/scripts/kconfig/streamline_config.pl index afbd54ac1d83..0d800820c3cd 100644 --- a/trunk/scripts/kconfig/streamline_config.pl +++ b/trunk/scripts/kconfig/streamline_config.pl @@ -113,7 +113,6 @@ sub find_config { # Get the build source and top level Kconfig file (passed in) my $ksource = $ARGV[0]; my $kconfig = $ARGV[1]; -my $lsmod_file = $ARGV[2]; my @makefiles = `find $ksource -name Makefile`; my %depends; @@ -122,8 +121,6 @@ sub find_config { my %objects; my $var; my $cont = 0; -my $iflevel = 0; -my @ifdeps; # prevent recursion my %read_kconfigs; @@ -149,15 +146,6 @@ sub read_kconfig { $state = "NEW"; $config = $1; - for (my $i = 0; $i < $iflevel; $i++) { - if ($i) { - $depends{$config} .= " " . $ifdeps[$i]; - } else { - $depends{$config} = $ifdeps[$i]; - } - $state = "DEP"; - } - # collect the depends for the config } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { $state = "DEP"; @@ -178,21 +166,6 @@ sub read_kconfig { # note if the config has a prompt $prompt{$config} = 1; - # Check for if statements - } elsif (/^if\s+(.*\S)\s*$/) { - my $deps = $1; - # remove beginning and ending non text - $deps =~ s/^[^a-zA-Z0-9_]*//; - $deps =~ s/[^a-zA-Z0-9_]*$//; - - my @deps = split /[^a-zA-Z0-9_]+/, $deps; - - $ifdeps[$iflevel++] = join ':', @deps; - - } elsif (/^endif/) { - - $iflevel-- if ($iflevel); - # stop on "help" } elsif (/^\s*help\s*$/) { $state = "NONE"; @@ -264,36 +237,8 @@ sub read_kconfig { my %modules; -if (defined($lsmod_file)) { - if ( ! -f $lsmod_file) { - die "$lsmod_file not found"; - } - if ( -x $lsmod_file) { - # the file is executable, run it - open(LIN, "$lsmod_file|"); - } else { - # Just read the contents - open(LIN, "$lsmod_file"); - } -} else { - - # see what modules are loaded on this system - my $lsmod; - - foreach $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) { - if ( -x "$dir/lsmod" ) { - $lsmod = "$dir/lsmod"; - last; - } -} - if (!defined($lsmod)) { - # try just the path - $lsmod = "lsmod"; - } - - open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod"; -} - +# see what modules are loaded on this system +open(LIN,"/sbin/lsmod|") || die "Cant lsmod"; while () { next if (/^Module/); # Skip the first line. if (/^(\S+)/) { diff --git a/trunk/security/integrity/ima/ima_iint.c b/trunk/security/integrity/ima/ima_iint.c index 2d4d05d92fda..0d83edcfc402 100644 --- a/trunk/security/integrity/ima/ima_iint.c +++ b/trunk/security/integrity/ima/ima_iint.c @@ -63,11 +63,12 @@ int ima_inode_alloc(struct inode *inode) spin_lock(&ima_iint_lock); rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); spin_unlock(&ima_iint_lock); - radix_tree_preload_end(); out: if (rc < 0) kmem_cache_free(iint_cache, iint); + radix_tree_preload_end(); + return rc; } diff --git a/trunk/security/selinux/ss/ebitmap.c b/trunk/security/selinux/ss/ebitmap.c index 04b6145d767f..68c7348d1acc 100644 --- a/trunk/security/selinux/ss/ebitmap.c +++ b/trunk/security/selinux/ss/ebitmap.c @@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; c_iter->bitmap[cmap_idx] - |= e_iter->maps[i] << cmap_sft; + |= e_iter->maps[cmap_idx] << cmap_sft; } e_iter = e_iter->next; } diff --git a/trunk/sound/aoa/fabrics/layout.c b/trunk/sound/aoa/fabrics/layout.c index 7a437da05646..586965f9605f 100644 --- a/trunk/sound/aoa/fabrics/layout.c +++ b/trunk/sound/aoa/fabrics/layout.c @@ -768,7 +768,7 @@ static int check_codec(struct aoa_codec *codec, "required property %s not present\n", propname); return -ENODEV; } - if (*ref != codec->node->phandle) { + if (*ref != codec->node->linux_phandle) { printk(KERN_INFO "snd-aoa-fabric-layout: " "%s doesn't match!\n", propname); return -ENODEV; diff --git a/trunk/sound/ppc/awacs.c b/trunk/sound/ppc/awacs.c index b36679384b27..2e156467b814 100644 --- a/trunk/sound/ppc/awacs.c +++ b/trunk/sound/ppc/awacs.c @@ -751,8 +751,8 @@ static void snd_pmac_awacs_suspend(struct snd_pmac *chip) static void snd_pmac_awacs_resume(struct snd_pmac *chip) { - if (of_machine_is_compatible("PowerBook3,1") - || of_machine_is_compatible("PowerBook3,2")) { + if (machine_is_compatible("PowerBook3,1") + || machine_is_compatible("PowerBook3,2")) { msleep(100); snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1] & ~MASK_PAROUT); @@ -780,16 +780,16 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip) } #endif /* CONFIG_PM */ -#define IS_PM7500 (of_machine_is_compatible("AAPL,7500") \ - || of_machine_is_compatible("AAPL,8500") \ - || of_machine_is_compatible("AAPL,9500")) -#define IS_PM5500 (of_machine_is_compatible("AAPL,e411")) -#define IS_BEIGE (of_machine_is_compatible("AAPL,Gossamer")) -#define IS_IMAC1 (of_machine_is_compatible("PowerMac2,1")) -#define IS_IMAC2 (of_machine_is_compatible("PowerMac2,2") \ - || of_machine_is_compatible("PowerMac4,1")) -#define IS_G4AGP (of_machine_is_compatible("PowerMac3,1")) -#define IS_LOMBARD (of_machine_is_compatible("PowerBook1,1")) +#define IS_PM7500 (machine_is_compatible("AAPL,7500") \ + || machine_is_compatible("AAPL,8500") \ + || machine_is_compatible("AAPL,9500")) +#define IS_PM5500 (machine_is_compatible("AAPL,e411")) +#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer")) +#define IS_IMAC1 (machine_is_compatible("PowerMac2,1")) +#define IS_IMAC2 (machine_is_compatible("PowerMac2,2") \ + || machine_is_compatible("PowerMac4,1")) +#define IS_G4AGP (machine_is_compatible("PowerMac3,1")) +#define IS_LOMBARD (machine_is_compatible("PowerBook1,1")) static int imac1, imac2; diff --git a/trunk/sound/ppc/burgundy.c b/trunk/sound/ppc/burgundy.c index 1f72e1c786bf..0accfe49735b 100644 --- a/trunk/sound/ppc/burgundy.c +++ b/trunk/sound/ppc/burgundy.c @@ -582,7 +582,7 @@ static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip) static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify) { if (chip->auto_mute) { - int imac = of_machine_is_compatible("iMac"); + int imac = machine_is_compatible("iMac"); int reg, oreg; reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); @@ -620,7 +620,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti */ int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip) { - int imac = of_machine_is_compatible("iMac"); + int imac = machine_is_compatible("iMac"); int i, err; /* Checks to see the chip is alive and kicking */ diff --git a/trunk/sound/ppc/pmac.c b/trunk/sound/ppc/pmac.c index 85081172403f..7bc492ee77ec 100644 --- a/trunk/sound/ppc/pmac.c +++ b/trunk/sound/ppc/pmac.c @@ -922,11 +922,11 @@ static void __devinit detect_byte_swap(struct snd_pmac *chip) } /* it seems the Pismo & iBook can't byte-swap in hardware. */ - if (of_machine_is_compatible("PowerBook3,1") || - of_machine_is_compatible("PowerBook2,1")) + if (machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook2,1")) chip->can_byte_swap = 0 ; - if (of_machine_is_compatible("PowerBook2,1")) + if (machine_is_compatible("PowerBook2,1")) chip->can_duplex = 0; } @@ -959,11 +959,11 @@ static int __devinit snd_pmac_detect(struct snd_pmac *chip) chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */ /* check machine type */ - if (of_machine_is_compatible("AAPL,3400/2400") - || of_machine_is_compatible("AAPL,3500")) + if (machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500")) chip->is_pbook_3400 = 1; - else if (of_machine_is_compatible("PowerBook1,1") - || of_machine_is_compatible("AAPL,PowerBook1998")) + else if (machine_is_compatible("PowerBook1,1") + || machine_is_compatible("AAPL,PowerBook1998")) chip->is_pbook_G3 = 1; chip->node = of_find_node_by_name(NULL, "awacs"); sound = of_node_get(chip->node); @@ -1033,8 +1033,8 @@ static int __devinit snd_pmac_detect(struct snd_pmac *chip) } if (of_device_is_compatible(sound, "tumbler")) { chip->model = PMAC_TUMBLER; - chip->can_capture = of_machine_is_compatible("PowerMac4,2") - || of_machine_is_compatible("PowerBook4,1"); + chip->can_capture = machine_is_compatible("PowerMac4,2") + || machine_is_compatible("PowerBook4,1"); chip->can_duplex = 0; // chip->can_byte_swap = 0; /* FIXME: check this */ chip->num_freqs = ARRAY_SIZE(tumbler_freqs); diff --git a/trunk/sound/soc/fsl/efika-audio-fabric.c b/trunk/sound/soc/fsl/efika-audio-fabric.c index 1a5b8e0d6a34..3326e2a1e863 100644 --- a/trunk/sound/soc/fsl/efika-audio-fabric.c +++ b/trunk/sound/soc/fsl/efika-audio-fabric.c @@ -55,7 +55,7 @@ static __init int efika_fabric_init(void) struct platform_device *pdev; int rc; - if (!of_machine_is_compatible("bplan,efika")) + if (!machine_is_compatible("bplan,efika")) return -ENODEV; card.platform = &mpc5200_audio_dma_platform; diff --git a/trunk/sound/soc/fsl/pcm030-audio-fabric.c b/trunk/sound/soc/fsl/pcm030-audio-fabric.c index 6644cba7cbf2..b928ef7d28eb 100644 --- a/trunk/sound/soc/fsl/pcm030-audio-fabric.c +++ b/trunk/sound/soc/fsl/pcm030-audio-fabric.c @@ -55,7 +55,7 @@ static __init int pcm030_fabric_init(void) struct platform_device *pdev; int rc; - if (!of_machine_is_compatible("phytec,pcm030")) + if (!machine_is_compatible("phytec,pcm030")) return -ENODEV; card.platform = &mpc5200_audio_dma_platform;